标签:tom 停止 资源 决定 info nbsp lock 检测 print
Java多线程,皆始于Thread。Thread是多线程的根,每一个线程的开启都始于Thread的start()方法。
看一个例子:
Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("thread begin..."); try { Thread.sleep(1000 * 30); } catch (Exception e) { } System.out.println("thread end"); } }); thread.start(); try { thread.join(); } catch (Exception e) { } System.out.println("main done");
new 一个 Thread,然后调用其 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容。 如果直接执行Thread的 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它。
调用 start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通方法调用,还是在主线程里执行,此外:
FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() { @Override public String call() throws Exception { return "hello world!"; } }); Thread thread = new Thread(futureTask); thread.start(); try { String result = futureTask.get(); System.out.println(result); } catch (Exception e) { } System.out.println("main done");
如果用Thread.stop()方法中止一个正在运行的线程:
public class MyThread { public static void main(String[] args) throws InterruptedException { StopThread thread = new StopThread(); thread.start(); // 休眠1秒,确保线程进入运行 Thread.sleep(1000); // 暂停线程 thread.stop(); //thread.interrupt(); // 确保线程已经销毁 while (thread.isAlive()) { } thread.print(); } private static class StopThread extends Thread { private int x = 0; private int y = 0; @Override public void run() { // 这是一个同步原子操作 synchronized (this) { ++x; try { // 休眠3秒,模拟耗时操作 Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } ++y; } } public void print() { System.out.println("x=" + x + " y=" + y); } } }
运行结果:
x=1 y=0
线程没有抛出异常,如果把stop改成interrupt,那么运行结果变为
x=1 y=1
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.meitu.helloworld.MyThread$StopThread.run(MyThread.java:34)
stop() 方法事实上已被废弃,它对线程的强制中断是不可预期的。
interrupt() 方法是一个比较温柔的做法,它更类似一个标志位。它不能中断线程,而是「通知线程应该中断了」,具体到底中断还是继续运行,应该由被通知的线程自己处理:
具体来说,当对一个线程,调用 interrupt() 时,
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);
参数:
public class ThreadTest { public static void main(String[] args) throws InterruptedException, IOException { final AtomicInteger mThreadNum = new AtomicInteger(1); ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), new ThreadFactory() { @Override public Thread newThread(@NotNull Runnable r) { Thread t = new Thread(r, "my-thread-" + mThreadNum.getAndIncrement()); System.out.println(t.getName() + " has been created"); return t; } }, new RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { System.err.println(r.toString() + " rejected"); } }); executor.prestartAllCoreThreads(); // 预启动所有核心线程 for (int i = 1; i <= 10; i++) { MyTask task = new MyTask(String.valueOf(i)); executor.execute(task); } executor.shutdown(); } static class MyTask implements Runnable { private String name; public MyTask(String name) { this.name = name; } @Override public void run() { try { System.out.println(this.toString() + " is running!"); Thread.sleep(3000); //让任务执行慢点 } catch (InterruptedException e) { e.printStackTrace(); } } @Override public String toString() { return "MyTask [name=" + name + "]"; } } }
运行结果:
my-thread-1 has been created
my-thread-2 has been created
my-thread-3 has been created
MyTask [name=1] is running!
my-thread-4 has been created
MyTask [name=3] is running!
MyTask [name=2] is running!
MyTask [name=5] is running!
MyTask [name=7] rejected
MyTask [name=8] rejected
MyTask [name=9] rejected
MyTask [name=10] rejected
MyTask [name=4] is running!
MyTask [name=6] is running!
其中线程线程1-4先占满了核心线程和最大线程数量,然后4、5线程进入等待队列,7-10线程被直接忽略拒绝执行,等1-4线程中有线程执行完后通知4、5线程继续执行。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
corePoolSize与maximumPoolSize相等,即其线程全为核心线程,是一个固定大小的线程池。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
看起来很像 newFixedThreadPool(1),但多了一层 FinalizableDelegatedExecutorService 包装,看下它的作用:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1); ((ThreadPoolExecutor) fixedThreadPool).setMaximumPoolSize(3); System.out.println(((ThreadPoolExecutor) fixedThreadPool).getMaximumPoolSize()); // 3 ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); ((ThreadPoolExecutor) singleThreadExecutor).setMaximumPoolSize(3); // 运行时异常 java.lang.ClassCastException //System.out.println(((ThreadPoolExecutor) singleThreadExecutor).getMaximumPoolSize());
可见,SingleThreadExecutor被包装后,无法成功向下转型。因此,SingleThreadExecutor被定以后,无法修改,做到了真正的Single。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
corePoolSize = 0,maximumPoolSize = Integer.MAX_VALUE,即其线程全为非核心线程,空闲超时会被释放。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
线程池自动关闭的两个条件:1、线程池的引用不可达;2、线程池中没有线程;
如果核心线程不为0,由于没有超时策略,所以并不会自动关闭。
当shutdown一个线程池后,继续提交任务,会执行拒绝策略;
public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 4, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); executor.execute(() -> System.out.println("before shutdown")); executor.shutdown(); executor.execute(() -> System.out.println("after shutdown")); }
shutdown一个线程池后,等待队列的任务仍会被继续执行,但如果用shutdownNow()
方法,则不执行队列中的任务;
shutdown和shutdownNow对正在执行的任务的影响是怎样的呢?
public class InteruptTest { public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); executor.execute(new Task("0")); Thread.sleep(1); executor.shutdownNow(); System.out.println("executor has been shutdown"); } static class Task implements Runnable { String name; public Task(String name) { this.name = name; } @Override public void run() { for (int i = 1; i <= 100 && !Thread.interrupted(); i++) { Thread.yield(); System.out.println("task " + name + " is running, round " + i); } } } }
运行结果:
task 0 is running, round 1
task 0 is running, round 2
task 0 is running, round 3
task 0 is running, round 4
task 0 is running, round 5
task 0 is running, round 6
task 0 is running, round 7
task 0 is running, round 8
task 0 is running, round 9
task 0 is running, round 10
task 0 is running, round 11
task 0 is running, round 12
task 0 is running, round 13
task 0 is running, round 14
task 0 is running, round 15
task 0 is running, round 16
task 0 is running, round 17
task 0 is running, round 18
task 0 is running, round 19
executor has been shutdown
task 0 is running, round 20
shutdownNow 会将正在执行任务的Thread.interrupted 置为true,如果线程检测了该状态,可以决定要不要停止运行。
标签:tom 停止 资源 决定 info nbsp lock 检测 print
原文地址:https://www.cnblogs.com/chenny7/p/13187826.html