本片文章以Java多线程简单实力为主,全部的例子选自java 编程思想第四版,全部都是自己手动对书 编写,如有疑问请直接留言。
import java.util.ArrayList;
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.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
*
*
* 并发编程使我们可以将程序划分为多个分离的、独立运行的任务。通过使用多线程机制,
* 这些独立任务(也被称为子任务)中的每一个都将由执行线程来驱动。
* 一个线程就是在进程中的一个单一的顺序控制流,因此,单个进程可以拥有多个并发执行的任务,
* 但是你的程序使得每个任务都好像有其自己的CPU一样。其底层机制是切分CPU时间,但通常你不需要考虑它。
*
* @create @author Henry @date 2016-11-16 重新查看Java编程思想线程部分。
*/
public class MainThread {
/**
*
* 单独跑run方法,
*
* @create @author Henry @date 2016-11-16
* 结果如下:
* #0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1),
* #0(Liftoff),
* @param args
*/
public static void main1(String[] args) {
LiftOff lauch = new LiftOff();
lauch.run();
}
/**
*
* 将其付给Thread跑
*
* @create @author Henry @date 2016-11-16
* 90%结果如下:
* Waiting for LiftOff
* #0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1),
* #0(Liftoff),
* @param args
*/
public static void main2(String[] args) {
Thread thread = new Thread(new LiftOff());
thread.start();
System.out.println("Waiting for LiftOff");
}
/**
*
* 启动5个子线程
*
* 输出说明不同任务的执行在线程被换进换出时混在了一起。这种交换是由线程调度器自动控制的。
* 如果在你的机器上有多个处理器,线程调度器将会在这些处理器之间默默地分发线程。
*
* 当main()创建Thread对象时,它并没有捕获任何对这些对象的引用。在使用普通对象时,
* 这对于垃圾回收来说是一场公平的游戏,但是在使用Thread时,情况就不同了。
* 每一个Thread都“注册”了它自己,因此确实有一个对它的引用,而且在它的任务退出其run()并死亡之前,
* 垃圾回收无法清除它。你可以从输出中看到,这些任务确实运行到了结束,
* 因此一个线程会创建一个单独的执行线程,在对start()的调用完成之后,它仍旧会继续存在。
*
* @create @author Henry @date 2016-11-16
* 结果可能如下:
* Waiting for LiftOff
* #1(9), #3(9), #0(9), #3(8), #2(9), #3(7), #1(8), #0(8), #2(8),
* #0(7),
* #4(9), #2(7), #0(6), #2(6), #3(6), #1(7), #4(8), #3(5), #1(6),
* #4(7),
* #0(5), #2(5), #3(4), #0(4), #1(5), #2(4), #4(6), #0(3), #2(3),
* #3(3),
* #4(5), #1(4), #0(2), #2(2), #4(4), #0(1), #3(2), #2(1), #1(3),
* #4(3),
* #0(Liftoff), #2(Liftoff), #3(1), #4(2), #1(2), #3(Liftoff),
* #1(1),
* #1(Liftoff), #4(1), #4(Liftoff),
* @param args
*/
public static void main3(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(new LiftOff()).start();
}
System.out.println("Waiting for LiftOff");
}
/**
*
* Java SE5的java.util.concurrent包中的执行器(Executor)将为你管理Thread 对象,
* 从而简化了并发编程。Excetor在客户端和任务执行之间提供了一个间接层;
* 与客户端直接执行任务不同,这个中介对象将执行任务。Executor允许你管理异步任务的执行,
* 而无须显式地管理线程的生命周期。Executor在JavaSE5/6中启动任务的优先方法。
* CachedThreadPool在程序执行过程中通常会创建与所需数量相同的线程,
* 然后在回收旧线程时停止创建新线程,因此它是合理的Executor的首选。
* 只有当这种方式会引发问题是,你才需要切换到FixedTreadPool。
*
* @create @author Henry @date 2016-11-16
*
* 执行可能结果如下:
* #4(9), #2(9), #0(9), #4(8), #0(8), #4(7), #0(7), #4(6), #0(6),
* #4(5), #0(5), #4(4), #0(4), #4(3), #0(3), #4(2), #1(9), #4(1),
* #4(Liftoff), #3(9), #0(2), #3(8), #1(8), #2(8), #0(1), #3(7),
* #0(Liftoff), #2(7), #1(7), #3(6), #2(6), #1(6), #3(5), #2(5),
* #1(5), #3(4), #2(4), #1(4), #3(3), #2(3), #1(3), #3(2), #3(1),
* #2(2), #2(1), #2(Liftoff), #1(2), #3(Liftoff), #1(1),
* #1(Liftoff),
* @param args
*/
public static void main4(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
/**
*
* 你可以很容易地将前面实例中的CachedThreadPool替换为不同类型的Executor.
* FixedThreadPool使用了有限的线程集来执行所提交的任务;
* 有了FixedThreadPool,你就可以一次性预先执行代价高昂的线程分配,
* 因而也就可以限制线程的数量了。这可以节省时间,因为你不用为每个任务都固定地付出
* 创建线程的开销。在事件驱动的系统中,需要线程的事件处理器,通过直接从池中获取线程,
* 也可以如你所愿地尽快得到服务。你不会滥用可获得的资源,因为FixedThreadPool使用的
* Thread对象的数量是有界的。
* SingleThreadExecutor就是线程数量为1的FixedThreadPool.
*
* @create @author Henry @date 2016-11-16
* 执行可能结果如下:
* #0(9), #3(9), #1(9), #2(9), #4(9), #1(8), #3(8), #1(7), #3(7),
* #1(6), #3(6), #1(5), #3(5), #1(4), #3(4), #1(3), #3(3), #1(2),
* #3(2), #1(1), #3(1), #4(8), #2(8), #0(8), #1(Liftoff), #2(7),
* #4(7), #0(7), #2(6), #3(Liftoff), #0(6), #4(6), #2(5), #0(5),
* #0(4), #2(4), #4(5), #0(3), #4(4), #0(2), #2(3), #4(3), #0(1),
* #2(2), #4(2), #0(Liftoff), #2(1), #4(1), #2(Liftoff),
* #4(Liftoff),
* @param args
*/
public static void main5(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
/**
*
* 用Future接收返回值:
*
* @create @author Henry @date 2016-11-16
* 输出结果如下:
* result of TaskWithResult 0
* result of TaskWithResult 1
* result of TaskWithResult 2
* result of TaskWithResult 3
* result of TaskWithResult 4
* result of TaskWithResult 5
* result of TaskWithResult 6
* result of TaskWithResult 7
* result of TaskWithResult 8
* result of TaskWithResult 9
*
* @param args
*/
public static void main6(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList<Future<String>>();
for (int i = 0; i < 10; i++)
results.add(exec.submit(new TaskWithResult(i)));
for (Future<String> fs : results) {
try {
System.out.println(fs.isDone());
System.out.println(fs.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
exec.shutdown();
}
}
}
/**
* @create @author Henry @date 2016-11-16
*
* 运行结果如下:
* #0(9), #2(9), #4(9), #1(9), #3(9), #4(8), #2(8), #0(8), #3(8),
* #1(8),
* #1(7), #0(7), #2(7), #4(7), #3(7), #1(6), #3(6), #0(6), #2(6),
* #4(6),
* #1(5), #4(5), #3(5), #2(5), #0(5), #3(4), #0(4), #2(4), #4(4),
* #1(4),
* #2(3), #4(3), #0(3), #3(3), #1(3), #3(2), #2(2), #1(2), #0(2),
* #4(2),
* #3(1), #4(1), #0(1), #2(1), #1(1), #3(Liftoff), #2(Liftoff),
* #1(Liftoff),
* #0(Liftoff), #4(Liftoff),
* @param args
*/
public static void main7(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++)
exec.execute(new SleepingTask());
exec.shutdown();
}
/**
*
* 测试线程优先级
*
* @create @author Henry @date 2016-11-16
* 运行结果如下:
* Thread[pool-1-thread-6,10,main]:5
* Thread[pool-1-thread-3,1,main]:5
* Thread[pool-1-thread-1,1,main]:5
* Thread[pool-1-thread-5,1,main]:5
* Thread[pool-1-thread-6,10,main]:4
* Thread[pool-1-thread-2,1,main]:5
* Thread[pool-1-thread-4,1,main]:5
* Thread[pool-1-thread-6,10,main]:3
* Thread[pool-1-thread-3,1,main]:4
* Thread[pool-1-thread-1,1,main]:4
* Thread[pool-1-thread-5,1,main]:4
* Thread[pool-1-thread-6,10,main]:2
* Thread[pool-1-thread-2,1,main]:4
* Thread[pool-1-thread-4,1,main]:4
* Thread[pool-1-thread-6,10,main]:1
* Thread[pool-1-thread-2,1,main]:3
* Thread[pool-1-thread-4,1,main]:3
* Thread[pool-1-thread-3,1,main]:3
* Thread[pool-1-thread-1,1,main]:3
* Thread[pool-1-thread-5,1,main]:3
* Thread[pool-1-thread-2,1,main]:2
* Thread[pool-1-thread-4,1,main]:2
* Thread[pool-1-thread-3,1,main]:2
* Thread[pool-1-thread-4,1,main]:1
* Thread[pool-1-thread-2,1,main]:1
* Thread[pool-1-thread-1,1,main]:2
* Thread[pool-1-thread-5,1,main]:2
* Thread[pool-1-thread-3,1,main]:1
* Thread[pool-1-thread-1,1,main]:1
* Thread[pool-1-thread-5,1,main]:1
*
* @param args
*/
public static void main8(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++)
exec.execute(new SimplePriorities(Thread.MIN_PRIORITY));
exec.execute(new SimplePriorities(Thread.MAX_PRIORITY));
exec.shutdown();
}
/**
* 只要有任何非后台线程还在运行,程序就不会终止。
* 比如:main()的就是一个非后台线程
*
* @create @author Henry @date 2016-11-16
* 运行结果如下:
* All daemons started
* Thread[Thread-1,5,main] com.think.no21.SimpleDaemons@e09713
* Thread[Thread-2,5,main] com.think.no21.SimpleDaemons@19b49e6
* Thread[Thread-8,5,main] com.think.no21.SimpleDaemons@47b480
* Thread[Thread-4,5,main] com.think.no21.SimpleDaemons@156ee8e
* Thread[Thread-0,5,main] com.think.no21.SimpleDaemons@de6f34
* Thread[Thread-6,5,main] com.think.no21.SimpleDaemons@83cc67
* Thread[Thread-3,5,main] com.think.no21.SimpleDaemons@10d448
* Thread[Thread-5,5,main] com.think.no21.SimpleDaemons@e0e1c6
* Thread[Thread-7,5,main] com.think.no21.SimpleDaemons@6ca1c
* Thread[Thread-9,5,main] com.think.no21.SimpleDaemons@1bf216a
* Thread[Thread-2,5,main] com.think.no21.SimpleDaemons@19b49e6
* Thread[Thread-8,5,main] com.think.no21.SimpleDaemons@47b480
* Thread[Thread-4,5,main] com.think.no21.SimpleDaemons@156ee8e
* Thread[Thread-0,5,main] com.think.no21.SimpleDaemons@de6f34
* Thread[Thread-6,5,main] com.think.no21.SimpleDaemons@83cc67
*
* @param args
* @throws Exception
*/
public static void main9(String[] args) throws Exception {
for (int i = 0; i < 10; i++) {
Thread daemon = new Thread(new SimpleDaemons());
daemon.setDaemon(true);
daemon.start();
}
System.out.println("All daemons started");
TimeUnit.MILLISECONDS.sleep(175);
}
/**
* 通过编写定制的ThreadFactory可以定制由Executor创建线程属性。
*
* @create @author Henry @date 2016-11-16
* 运行结果如下:
* All daemons started
* Thread[Thread-1,5,main] com.think.no21.DaemonFromFactory@109a4c
* Thread[Thread-3,5,main] com.think.no21.DaemonFromFactory@201f9
* Thread[Thread-5,5,main] com.think.no21.DaemonFromFactory@1cf8583
* Thread[Thread-2,5,main] com.think.no21.DaemonFromFactory@14693c7
* Thread[Thread-4,5,main] com.think.no21.DaemonFromFactory@901887
* Thread[Thread-6,5,main] com.think.no21.DaemonFromFactory@665753
* Thread[Thread-8,5,main] com.think.no21.DaemonFromFactory@ef22f8
* Thread[Thread-9,5,main] com.think.no21.DaemonFromFactory@4a65e0
* Thread[Thread-7,5,main] com.think.no21.DaemonFromFactory@3a6727
* Thread[Thread-0,5,main] com.think.no21.DaemonFromFactory@1e0cf70
* Thread[Thread-1,5,main] com.think.no21.DaemonFromFactory@109a4c
* Thread[Thread-3,5,main] com.think.no21.DaemonFromFactory@201f9
* Thread[Thread-5,5,main] com.think.no21.DaemonFromFactory@1cf8583
* Thread[Thread-7,5,main] com.think.no21.DaemonFromFactory@3a6727
* Thread[Thread-9,5,main] com.think.no21.DaemonFromFactory@4a65e0
* Thread[Thread-0,5,main] com.think.no21.DaemonFromFactory@1e0cf70
* Thread[Thread-6,5,main] com.think.no21.DaemonFromFactory@665753
* Thread[Thread-4,5,main] com.think.no21.DaemonFromFactory@901887
* Thread[Thread-2,5,main] com.think.no21.DaemonFromFactory@14693c7
* Thread[Thread-8,5,main] com.think.no21.DaemonFromFactory@ef22f8
* Thread[Thread-9,5,main] com.think.no21.DaemonFromFactory@4a65e0
* Thread[Thread-7,5,main] com.think.no21.DaemonFromFactory@3a6727
* Thread[Thread-8,5,main] com.think.no21.DaemonFromFactory@ef22f8
* Thread[Thread-2,5,main] com.think.no21.DaemonFromFactory@14693c7
* Thread[Thread-0,5,main] com.think.no21.DaemonFromFactory@1e0cf70
* Thread[Thread-6,5,main] com.think.no21.DaemonFromFactory@665753
* Thread[Thread-4,5,main] com.think.no21.DaemonFromFactory@901887
* Thread[Thread-5,5,main] com.think.no21.DaemonFromFactory@1cf8583
* Thread[Thread-3,5,main] com.think.no21.DaemonFromFactory@201f9
* Thread[Thread-1,5,main] com.think.no21.DaemonFromFactory@109a4c
* Thread[Thread-9,5,main] com.think.no21.DaemonFromFactory@4a65e0
* Thread[Thread-7,5,main] com.think.no21.DaemonFromFactory@3a6727
* Thread[Thread-5,5,main] com.think.no21.DaemonFromFactory@1cf8583
* Thread[Thread-8,5,main] com.think.no21.DaemonFromFactory@ef22f8
* Thread[Thread-2,5,main] com.think.no21.DaemonFromFactory@14693c7
* Thread[Thread-0,5,main] com.think.no21.DaemonFromFactory@1e0cf70
* Thread[Thread-6,5,main] com.think.no21.DaemonFromFactory@665753
* Thread[Thread-4,5,main] com.think.no21.DaemonFromFactory@901887
* Thread[Thread-3,5,main] com.think.no21.DaemonFromFactory@201f9
* Thread[Thread-1,5,main] com.think.no21.DaemonFromFactory@109a4c
* Thread[Thread-5,5,main] com.think.no21.DaemonFromFactory@1cf8583
* Thread[Thread-7,5,main] com.think.no21.DaemonFromFactory@3a6727
* Thread[Thread-9,5,main] com.think.no21.DaemonFromFactory@4a65e0
* Thread[Thread-3,5,main] com.think.no21.DaemonFromFactory@201f9
* Thread[Thread-1,5,main] com.think.no21.DaemonFromFactory@109a4c
* Thread[Thread-0,5,main] com.think.no21.DaemonFromFactory@1e0cf70
* Thread[Thread-2,5,main] com.think.no21.DaemonFromFactory@14693c7
* Thread[Thread-8,5,main] com.think.no21.DaemonFromFactory@ef22f8
* Thread[Thread-4,5,main] com.think.no21.DaemonFromFactory@901887
* Thread[Thread-6,5,main] com.think.no21.DaemonFromFactory@665753
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool(new DaemonThreadFactory());
for (int i = 0; i < 10; i++)
exec.execute(new DaemonFromFactory());
System.out.println("All daemons started");
TimeUnit.MILLISECONDS.sleep(500);
}
}
/**
*
* 简单的对象实现Runnable接口
*
* @create @author Henry @date 2016-11-16
*/
class LiftOff implements Runnable {
protected int countDown = 10;
private static int taskCount = 0;
private final int id = taskCount++;
public LiftOff() {
}
public LiftOff(int countDown) {
this.countDown = countDown;
}
public String status() {
return "#" + id + "(" + (countDown > 0 ? countDown : "Liftoff") + "), ";
}
@Override
public void run() {
while (countDown-- > 0) {
System.out.print(status());
/**
* Thread.yield()的调用是对线程调度器(java线程机制的一部分,可以将CPU从一个线程转移给另一个线程)的一种建议,
* 它在声明:“我已经执行完生命周期中最重要的部分了,此刻正是切换给其他任务执行一段时间的大好时机。”
* 这完全是选择性的,但是这里使用它是因为它会在这些示例中产生更加有趣的输出:你更有可能会看到任务换进换出的证据。
*
*/
Thread.yield();
}
}
}
/**
*
* 声明带返回值的线程类。
*
* @create @author Henry @date 2016-11-16
*/
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
@Override
public String call() throws Exception {
return "result of TaskWithResult " + id;
}
}
/**
*
* 影响人物行为的一种简单方法是调用sleep(),这将使任务中止执行给定的时间。
* 在LiftOff类中,要是把对yield()的调用换成是调用sleep()
*
* @create @author Henry @date 2016-11-16
*/
class SleepingTask extends LiftOff {
@Override
public void run() {
try {
while (countDown-- > 0) {
System.out.print(status());
// Old-style;
// Thread.sleep(100);
// java SE5/6-style;
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
System.err.println("Interrupted");
}
}
}
/**
*
* 测试线程的优先级的类
*
* @create @author Henry @date 2016-11-16
*/
class SimplePriorities implements Runnable {
private int countDown = 5;
private volatile double d;// No optimization
private int priority;
public SimplePriorities(int priority) {
this.priority = priority;
}
@Override
public String toString() {
return Thread.currentThread() + ":" + countDown;
}
@Override
public void run() {
Thread.currentThread().setPriority(priority);
while (true) {
// An expensive,interruptable operation:
for (int i = 1; i < 100000; i++) {
d += (Math.PI + Math.E) / (double) i;
if (i % 1000 == 0)
Thread.yield();
}
System.out.println(this);
if (--countDown == 0)
return;
}
}
}
/**
* 后台线程,是指在程序运行的时候再后台提供的一种服务的线程,并且
* 这种线程不属于程序中不可或缺的部分。因此,当所有的非后台线程结束时,
* 程序也就终止了,同时会杀死进程中的所有后台线程。
*
* @create @author Henry @date 2016-11-16
*
*/
class SimpleDaemons implements Runnable {
@Override
public void run() {
try {
while (true) {
TimeUnit.MILLISECONDS.sleep(100);
System.out.println(Thread.currentThread() + " " + this);
}
} catch (InterruptedException e) {
System.out.println("sleep() interrupted");
}
}
}
/**
* 创建ThreadFactory,将后台状态全部设置为true
*
* @create @author Henry @date 2016-11-16
*
*/
class DaemonThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
/**
* 创建一个新的DeamonFromFactory
*
* @create @author Henry @date 2016-11-16
*
*/
class DaemonFromFactory implements Runnable {
@Override
public void run() {
try {
while (true) {
TimeUnit.MILLISECONDS.sleep(100);
System.out.println(Thread.currentThread() + " " + this);
}
} catch (InterruptedException e) {
System.out.println("interrupted");
}
}
}
/**
* 每个静态的ExecutorService创建方法都被重载为接受一个ThreadFactory对象,
* 而这个对象将被用来创建新的线程:
* @create @author Henry @date 2016-11-16
*
*/
class DaemonThreadPoolExecutor extends ThreadPoolExecutor {
public DaemonThreadPoolExecutor() {
super(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),new DaemonThreadFactory());
}
}
import java.util.concurrent.TimeUnit;
/**
* 如果是一个后台线程,那么它创建的任何线程江北自动设置成后台线程,
* 例子如下。
* @create @author Henry @date 2016-11-18
*
*/
public class Daemons {
/**
* 运行结果如下:
* d.isDaemon = true.
* DaemonSpawn 0 started.
* DaemonSpawn 1 started.
* DaemonSpawn 2 started.
* DaemonSpawn 3 started.
* DaemonSpawn 4 started.
* DaemonSpawn 5 started.
* DaemonSpawn 6 started.
* DaemonSpawn 7 started.
* DaemonSpawn 8 started.
* DaemonSpawn 9 started.
* t[0].isDaemon()=true
* t[1].isDaemon()=true
* t[2].isDaemon()=true
* t[3].isDaemon()=true
* t[4].isDaemon()=true
* t[5].isDaemon()=true
* t[6].isDaemon()=true
* t[7].isDaemon()=true
* t[8].isDaemon()=true
* t[9].isDaemon()=true
*
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
Thread d =new Thread(new Daemon());
d.setDaemon(true);
d.start();
System.out.println("d.isDaemon = "+d.isDaemon()+".");
TimeUnit.SECONDS.sleep(1);
}
}
/**
* 在主线程下创建的线程中包含此子线程。
* @create @author Henry @date 2016-11-18
*
*/
class Daemon implements Runnable {
private Thread[] t = new Thread[10];
@Override
public void run() {
for (int i = 0; i < t.length; i++) {
t[i] = new Thread(new DaemonSpawn());
t[i].start();
System.out.println("DaemonSpawn " + i + " started.");
}
for (int i = 0; i < t.length; i++)
System.out.println("t[" + i + "].isDaemon()=" + t[i].isDaemon());
while (true)
Thread.yield();
}
}
/**
*
* 在子线程内再创建的子线程。
* @create @author Henry @date 2016-11-18
*/
class DaemonSpawn implements Runnable {
@Override
public void run() {
while (true) {
Thread.yield();
}
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 你应该意识到后台进程在不执行finally子句的情况下就会终止其run()方法.
* 此例子说明,当其中一个后台线程结束的时候,其他的后台线程是不能终止的。
* @create @author Henry @date 2016-11-18
*
*/
class ADeamon implements Runnable {
private static int taskCount = 0;
private final int id = taskCount++;
@Override
public void run() {
try {
System.out.println(id+" Starting ADaemon");
if(id!=1){
TimeUnit.SECONDS.sleep(3);
}
} catch (InterruptedException e) {
System.out.println("Exiting via InterruptedExecption");
}finally{
System.out.println(id+" This should always run?");
}
}
}
/**
* 当你运行这个程序时,你将看到finally子句就不会执行,
* 但是如果你注释掉对setDaemon()的调用,就会看到finally子句将会执行。
*
* @create @author Henry @date 2016-11-18
*
*/
public class DaemonsDontRunFinally {
/**
*
* @create @author Henry @date 2016-11-18
* 运行结果如下:
* Starting ADaemon
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// for (int i = 0; i < 3; i++) {
// Thread t=new Thread(new ADeamon());
// t.setDaemon(true);
// t.start();
// }
ExecutorService exec=Executors.newCachedThreadPool();
for (int i = 0; i < 3; i++)
exec.execute(new ADeamon());
TimeUnit.SECONDS.sleep(2);
exec.shutdown();
TimeUnit.SECONDS.sleep(10);
System.out.println("hello");
}
}