线程的创建方式:
使用Thread:
定义Thread的子类并重写run()方法
创建Thread子类的实例
调用该对象的start()方法启动线程
使用Runnable:
定义Runnable接口的实现类,并重写该接口的run()方法
创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象
调用该对象的start()方法启动线程
使用Callable和Future:
创建Callable接口的实现类,并实现call()方法
使用FutureTask类来包装Callable对象
使用FutureTask对象作为Thread对象的target来创建Thread对象
调用该对象的start()方法启动线程
调用FutureTask对象的get()方法获取子线程执行结束后的返回值
三种方式的对比:
Callable接口里定义的方法可以有返回值,可以抛出异常
实现Runnable和Callable接口还可以继承其他类
继承Thread类直接使用this访问当前线程,实现接口需要使用Thread.currentThread()方法获取当前线程
线程的生命周期:
新建 -->就绪-->运行-->阻塞-->死亡
控制线程:
join线程:
当某个线程执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的join线程执行完为止
后台线程:
如果所有的前台线程都死亡,后台线程会自动死亡,调用Thread对象的setDaemon(true)方法可将指定线程设置成后台线程
线程睡眠:
调用Thread类的静态sleep()方法让当前正在执行的线程暂停一段时间,并进入阻塞状态
线程让步:
调用Thread类的静态yield()方法让当前线程暂停,并进入就绪状态
改变线程的优先级:
每个线程执行时都具有一定的优先级,优先级越高越有希望被执行,通过Thread类的setPriority()和getPriority()方法来设置和返回指定线程的优先级,新线程的优先级和创建新线程的线程具有相同优先级
线程同步:
同步代码块
同步方法
同步锁
使用特殊域变量(volatile)
使用ThreadLocal
使用阻塞队列(LinkedBlockingQueue)
使用原子变量(java.util.concurrent.atomic包中提供)
线程通信:
使用同步代码块或同步方法时,可以借助于Object类提供的wait()、notify()、notifyAll()实现通信,对于同步方法,该类的实例就是同步监听器,对于同步代码块,同步监听器时synchronized后括号里的对象
如果使用Lock保证同步需要使用Condition控制通信,通过调用Lock对象的newCondition()方法获取Condition实例,Condition提供了await()、signal()、signalAll()
使用阻塞队列(BlockingQueue)
处理线程异常:
如果线程执行过程中抛出了一个未处理异常,JVM在结束该线程之前会自动查找是否有对应的Thread.UncaughtExceptionHandler对象,如果找到该处理器对象,则会调用该对象的uncaughtException(Thread t, Throwable e)方法来处理该异常啊,Thread提供了两个方法来设置异常处理器:setDefaultUncaughtExceptionHandler()、setUncaughtExceptionHandler()
线程池:
通过Executors工厂类来产生线程池使用步骤:
调用Executors类的静态工厂方法创建一个ExecutorService对象
创建Runnable或则Callable实现类的实例
调用ExecutorService对象的submit()方法来提交线程执行任务
不想提交任何任务时,调用ExecutorService对象的shutdown()方法关闭线程池
通过使用ForkJoinPool创建线程池:
区别:ForkJoinPool可以将一个任务分成子任务,让几个线程同时执行