茌平建设局网站,顺庆区城乡规划建设局门户网站,wordpress蜘蛛插件,网站建设维保免费内容四种线程池
Java 里面线程池的顶级接口是 Executor#xff0c;但是严格意义上讲 Executor 并不是一个线程池#xff0c;而只是一个执行线程的工具。真正的线程池接口是 ExecutorService。 newCachedThreadPool
创建一个可根据需要创建新线程的线程池#xff0c;但是在以前…四种线程池
Java 里面线程池的顶级接口是 Executor但是严格意义上讲 Executor 并不是一个线程池而只是一个执行线程的工具。真正的线程池接口是 ExecutorService。 newCachedThreadPool
创建一个可根据需要创建新线程的线程池但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程如果线程可用。如果现有线程没有可用的则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此长时间保持空闲的线程池不会使用任何资源。
newFixedThreadPool
创建一个可重用固定线程数的线程池以共享的无界队列方式来运行这些线程。在任意点在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务则在有可用线程之前附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止那么一个新线程将代替它执行后续的任务如果需要。在某个线程被显式地关闭之前池中的线程将一直存在。
newScheduledThreadPool
创建一个线程池它可安排在给定延迟后运行命令或者定期地执行。
ScheduledExecutorService scheduledThreadPool Executors.newScheduledThreadPool(3);
scheduledThreadPool.schedule(newRunnable() {Overridepublic void run () {System.out.println(延迟三秒);}
},3, TimeUnit.SECONDS);scheduledThreadPool.scheduleAtFixedRate(newRunnable() {Overridepublic void run () {System.out.println(延迟 1 秒后每三秒执行一次);}
},1, 3, TimeUnit.SECONDS);newSingleThreadExecutor
Executors.newSingleThreadExecutor()返回一个线程池这个线程池只有一个线程,这个线程池可以在线程死后或发生异常时重新启动一个线程来替代原来的线程继续执行下去
线程生命周期**(状态)**
当线程被创建并启动以后它既不是一启动就进入了执行状态也不是一直处于执行状态。在线程的生命周期中它要经过新建(New)、就绪Runnable、运行Running、阻塞(Blocked)和死亡(Dead)5 种状态。尤其是当线程启动以后它不可能一直霸占着 CPU 独自运行所以 CPU 需要在多条线程之间切换于是线程状态也会多次在运行、阻塞之间切换。
新建状态NEW
当程序使用 new 关键字创建了一个线程之后该线程就处于新建状态此时仅由 JVM 为其分配内存并初始化其成员变量的值。
就绪状态RUNNABLE
当线程对象调用了 start()方法之后该线程处于就绪状态。Java 虚拟机会为其创建方法调用栈和程序计数器等待调度运行。
运行状态RUNNING
如果处于就绪状态的线程获得了 CPU开始执行 run()方法的线程执行体则该线程处于运行状态。
阻塞状态BLOCKED
阻塞状态是指线程因为某种原因放弃了 cpu 使用权也即让出了 cpu timeslice暂时停止运行。直到线程进入可运行(runnable)状态才有机会再次获得 cpu timeslice 转到运行(running)状态。阻塞的情况分三种
等待阻塞o.wait-等待对列
运行(running)的线程执行 o.wait()方法JVM 会把该线程放入等待队列(waitting queue)中。
同步阻塞(lock-锁池)
运行(running)的线程在获取对象的同步锁时若该同步锁被别的线程占用则 JVM 会把该线程放入锁池(lock pool)中。
其他阻塞(sleep/join)
运行(running)的线程执行 Thread.sleep(long ms)或 t.join()方法或者发出了 I/O 请求时JVM 会把该线程置为阻塞状态。当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O处理完毕时线程重新转入可运行(runnable)状态。
线程死亡DEAD
线程会以下面三种方式结束结束后就是死亡状态。
正常结束
run()或 call()方法执行完成线程正常结束。
异常结束
线程抛出一个未捕获的 Exception 或 Error。
调用 stop
直接调用该线程的 stop()方法来结束该线程—该方法通常容易导致死锁不推荐使用。 终止线程 4 种方式
正常运行结束
程序运行结束线程自动结束。
使用退出标志退出线程
一般 run()方法执行完线程就会正常结束然而常常有些线程是伺服线程。它们需要长时间的运行只有在外部某些条件满足的情况下才能关闭这些线程。使用一个变量来控制循环例如最直接的方法就是设一个 boolean 类型的标志并通过设置这个标志为 true 或 false 来控制 while循环是否退出代码示例
public class ThreadSafe extends Thread {public volatile boolean exit false;public void run() {while (!exit) {//do something}}
}
定义了一个退出标志 exit当 exit 为 true 时while 循环退出exit 的默认值为 false.在定义 exit时使用了一个 Java 关键字 volatile这个关键字的目的是使 exit 同步也就是说在同一时刻只能由一个线程来修改 exit 的值。
Interrupt 方法结束线程
使用 interrupt()方法来中断线程有两种情况 线程处于阻塞状态如使用了 sleep,同步锁的 wait,socket 中的 receiver,accept 等方法时会使线程处于阻塞状态。当调用线程的 interrupt()方法时会抛出 InterruptException 异常。阻塞中的那个方法抛出这个异常通过代码捕获该异常然后 break 跳出循环状态从而让我们有机会结束这个线程的执行。通常很多人认为只要调用 interrupt 方法线程就会结束实际上是错的 一定要先捕获 InterruptedException 异常之后通过 break 来跳出循环才能正常结束 run 方法。 线程未处于阻塞状态使用 isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时中断标志就会置 true和使用自定义的标志来控制循环是一样的道理。
public class ThreadSafe extends Thread {public void run() {while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出try{Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出}catch(InterruptedException e){e.printStackTrace();break;//捕获到异常之后执行 break 跳出循环}}}}stop 方法终止线程线程不安全
程序中可以直接使用 thread.stop()来强行终止线程但是 stop 方法是很危险的就象突然关闭计算机电源而不是按正常程序关机一样可能会产生不可预料的结果不安全主要是thread.stop()调用之后创建子线程的线程就会抛出 ThreadDeatherror 的错误并且会释放子线程所持有的所有锁。一般任何进行加锁的代码块都是为了保护数据的一致性如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放(不可控制)那么被保护数据就有可能呈现不一致性其他线程在使用这些被破坏的数据时有可能导致一些很奇怪的应用程序错误。因此并不推荐使用 stop 方法来终止线程。
sleep 与 wait 区别 对于 sleep()方法我们首先要知道该方法是属于 Thread 类中的。而 wait()方法则是属于Object 类中的。 sleep()方法导致了程序暂停执行指定的时间让出 cpu 该其他线程但是他的监控状态依然保持者当指定的时间到了又会自动恢复运行状态。 在调用 sleep()方法的过程中线程不会释放对象锁。 而当调用 wait()方法的时候线程会放弃对象锁进入等待此对象的等待锁定池只有针对此对象调用 notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
start 与 run 区别 **start**方法来启动线程真正实现了多线程运行。这时无需等待 run 方法体代码执行完毕可以直接继续执行下面的代码。 通过调用 Thread 类的 start()方法来启动一个线程 这时此线程是处于就绪状态 并没有运行。 方法 run()称为线程体它包含了要执行的这个线程的内容线程就进入了运行状态开始运行 run 函数当中的代码。 Run 方法运行结束 此线程终止。然后 CPU 再调度其它线程。
JAVA 后台线程 定义守护线程–也称“服务线程”他是后台线程它有一个特性即为用户线程 提供 公共服务在没有用户线程可服务时会自动离开。 优先级守护线程的优先级比较低用于为系统中的其它对象和线程提供服务。 设置通过 setDaemon(true)来设置线程为“守护线程”将一个用户线程设置为守护线程的方式是在 线程对象创建 之前 用线程对象的 setDaemon 方法。 在 Daemon 线程中产生的新线程也是 Daemon 的。 线程则是 JVM 级别的以 Tomcat 为例如果你在 Web 应用中启动一个线程这个线程的生命周期并不会和 Web 应用程序保持同步。也就是说即使你停止了 Web 应用这个线程依旧是活跃的。 example: 垃圾回收线程就是一个经典的守护线程当我们的程序中不再有任何运行的Thread,程序就不会再产生垃圾垃圾回收器也就无事可做所以当垃圾回收线程是 JVM 上仅剩的线程时垃圾回收线程会自动离开。它始终在低级别的状态中运行用于实时监控和管理系统中的可回收资源。 生命周期守护进程Daemon是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。也就是说守护线程不依赖于终端但是依赖于系统与系统“同生共死”。当 JVM 中所有的线程都是守护线程的时候JVM 就可以退出了如果还有一个或以上的非守护线程则 JVM 不会退出。