Java多线程

来源:互联网 发布:淘宝质量好的女包店 编辑:程序博客网 时间:2024/06/02 06:00
1.Runnable接口与Callable接口的区别

    Runnable接口中的方法签名为:public void run();该方法不能声明抛出受检查的异常,但在方法体内可以捕获并处理异常;

    Callable<V>接口中的方法签名:public V call() throws Exception;该方法能够抛出受检查的异常,能够返回一个V类型的值;

    实现这两个接口的对象都可以用来构造线程对象。

2.Future<V>接口

    该接口能够封装Callable接口的返回值,并提供了一系列的方法来获取call方法的计算结果。

  • boolean cancel(boolean mayInterruptIfRunning):该方法试图取消对任务的执行;
  • boolean isCancelled():如果在任务正常完成前将其取消,则返回 true;
  • boolean isDone():如果任务已完成,则返回 true。 可能由于正常终止、异常或取消而完成,在所有这些情况中,此方法都将返回 true;
  • V get():如有必要,则阻塞等待计算完成,然后获取其结果;
  • V get(long timeout, TimeUnit unit):如有必要,最多等待为使计算完成所给定的时间之后,获取其结果,否则抛出异常
    FutureTask 类是 Future 的一个实现,并实现了Runnable接口,所以可通过 Executor 来执行。下面分别演示Future接口和FutureTask类的使用,单独使用Future接口需要通过Executor.submit方法返回future对象,否则使用FutureTask类则可以使用excute来提交执行。

import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.FutureTask;class RetString implements Callable<String>{private String retString;public RetString(String s) {this.retString = s;}public String call() throws Exception{return retString;}}public class CallableThreadTest {public static void main(String[] args) throws     InterruptedException, ExecutionException {/** * 使用Future接口,需要使用submit方法提交任务,该方法返回一个future对象 */ExecutorService exec = Executors.newFixedThreadPool(2);Future<String>  future = exec.submit(new RetString("Hello World"));/** * 使用FutureTask类,直接使用execute方法 */FutureTask<String> fTask = new FutureTask<String>(new RetString("Good Night"));exec.execute(fTask);if(future.isDone()) System.out.println(future.get());if(fTask.isDone()) System.out.println(fTask.get());exec.shutdown();}}
3.使用Executor
    该接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法;ExecutorService是该接口的一个子接口。通过Executors工厂类的静态方法来创建ExecutorService接口对象。
  • static ExecutorService newCachedThreadPool():创建一个可根据需要创建新线程的线程池;
  • static ExecutorService newCachedThreadPool(ThreadFactory threadFactory):创建一个可根据需要创建新线程的线程池,在需要时使用提供的 ThreadFactory 创建新线程;
  • static ExecutorService newFixedThreadPool(int nThreads):创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程;
  • static ExecutorService newFixedThreadPool(int nThreads,ThreadFactory threadFactory);
  • static ExecutorService newSingleThreadExecutor():创建一个使用单个worker线程的Executor,以无界队列方式来运行该线程。如果提交多个任务,这些任务将排队,每个任务在下个任务开始i之前运行结束
  • static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) :创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
  • static ScheduledExecutorService newSingleThreadScheduledExecutor() :创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
    ThreadFactory是一个接口,该接口允许允许应用程序使用特殊的线程子类、属性等,使用线程工厂就无需再手工编写对 new Thread 的调用,它根据需要创建新线程的对象。如下面的代码是一个简单的线程工厂,该工厂根据传进来的Runnable对象创建后台线程。
class SimpleThreadFactory implements ThreadFactory {   public Thread newThread(Runnable r) { //需要要实现的方法     Thread t = new Thread(r);     t.setDaemon(true);     return t;   } }
    可通过下面的方法向ExecutorService提交要执行的任务和关闭任务:
  • Future<T> submit(Callable<T> task):提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future;
  • Future<?> submit(Runnable task):提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future;结束后返回null;
  • <T> Future<T> submit(Runnable task, T result):提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功完成时将会返回给定的结果T;
  • void execute(Runnable command):在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定
  • void shutdown():启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。
  • List<Runnable> shutdownNow():试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表,该方法其实是发送interrupt()调用给它启动的所有线程;
    使用ScheduledExecutorService,该接口可以在指定延迟后或周期性地执行线程任务的线程池,为ExecutorService接口的子接口,提供以下的方法:
  • <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit):创建并执行在给定延迟后启用的ScheduledFuture;
  • ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) :创建并执行在给定延迟后启用的一次性操作,在delay后执行
  • ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit):创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推;
  • ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) :创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟
4.线程中断
    Thread.interrupt()方法不会中断一个正在运行的线程。这一方法实际上完成的是,在线程受到阻塞或者正在尝试阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。当抛出异常或者调用Thread.interrupted()时,中断状态将被复位。所以,只有在Object.wait, Thread.join和Thread.sleep这三个方法上已经阻塞或者尝试阻塞的线程,当中断位被设置时,才会抛出异常,中断状态被清除,否则中断不会真正中断线程的执行。I/O和在synchronized块上的等待是不可中断的,可以通过关闭任务在其上发生阻塞的底层资源来中断。
5.捕获线程异常
    异常不能跨线程传播,因此其他线程中抛出的异常不会传播到Main线程。Thread.UncaughtExceptionHandler接口允许在每个Thread对象上附着一个异常处理器。该接口中的方法声明为:public void uncaughtException(Thread t, Throwable e);对线程对象调用setUncaughtExceptionHandler()方法可以为线程设置异常处理器。

原创粉丝点击