package threadtest; /** * 事实上,Runnable类称作Task更加确切 * 真正的线程是执行单位,应该是Thread或Executor */ public class TestThread extends Thread { private static int id = 1; @Override public void run() { System.out.println(this + " id: " + id++); } } package threadtest; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Executor { public static void main(String[] args) { // 创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们 // 它通常会创建与所需数量相同的线程,然后在回收旧线程时停止创建新线程 ExecutorService executor = Executors.newCachedThreadPool(); // 创建一个可重用固定线程集合的线程池,以共享的无界队列方式来运行这些线程 // 一般来讲只有当 cachedThreadPool 会引发问题时才需要使用它 // ExecutorService executor = Executors.newFixedThreadPool(3); // 相当与使用 newFixedThreadPool(1) // 可以知道当线程数只有1的时候,所有的任务将会是顺序执行,而不能并发 // ExecutorService executor = Executors.newSingleThreadExecutor(); // 执行线程 for (int i = 0; i < 5; i++) executor.execute(new TestThread()); // 启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用 executor.shutdown(); } }
Thread[Thread-0,5,main] id: 1
Thread[Thread-2,5,main] id: 2
Thread[Thread-1,5,main] id: 3
Thread[Thread-4,5,main] id: 4
Thread[Thread-3,5,main] id: 5
Callable接口,作用是可以使用ExecutorService.submit()方法执行Callable线程,并获得线程的执行结果
package threadtest; import java.util.concurrent.Callable; /** * 线程返回值,使用Callable接口实现 */ public class CallThread implements Callable<String> { @Override public String call() throws Exception { return this + " Result: This is a thread callback result!"; } } package threadtest; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class CallTest { public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); // 使用一个 ArrayList 存储 Callable 的回调结果 List<Future<String>> results = new ArrayList<Future<String>>(); // 使用 executor 的submit() 方法获取回调结果,结果类型是 Future for (int i = 0; i < 5; i++) results.add(executor.submit(new CallThread())); executor.shutdown(); for (Future<String> f : results) { try { // Future 的 get() 方法可以获取 Callable 的 call() 方法结果 System.out.println(f.get()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
threadtest.CallThread@a87e7b Result: This is a thread callback result!
threadtest.CallThread@11be57f Result: This is a thread callback result!
threadtest.CallThread@780af5 Result: This is a thread callback result!
threadtest.CallThread@11775bc Result: This is a thread callback result!
threadtest.CallThread@132a4df Result: This is a thread callback result!
线程优先级的示范,线程优先级越高,则执行的顺序越靠前
package threadtest; public class PriorityThread extends Thread { private int priority; private volatile double d; public PriorityThread(int priority) { this.priority = priority; } @Override public void run() { // setPriority() 应该在 run() 方法的开头写上 Thread.currentThread().setPriority(priority); for (int i = 0; i < 10000000; i++) { d += (Math.PI + Math.E) / (double) i; if (i % 1000 == 0) Thread.yield(); } System.out.println(Thread.currentThread() + "|" + this); } } package threadtest; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class PriorityTest { public static void main(String[] args) { // 需要注意,使用 ExecutorService 来管理线程 // Thread.currentThread() 和 this 是不一样的 // 所以应该尽量使用 Thread.currentThread() 避免这个问题发生 ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 4; i++) { exec.execute(new PriorityThread(Thread.MIN_PRIORITY)); } exec.execute(new PriorityThread(Thread.MAX_PRIORITY)); // 测试 currentThread() 和 this 的区别,此处使用start是一样的 (new PriorityThread(1)).start(); exec.shutdown(); } }
Thread[Thread-5,1,main]|Thread[Thread-5,1,main]
Thread[pool-1-thread-5,10,main]|Thread[Thread-4,5,main]
Thread[pool-1-thread-2,1,main]|Thread[Thread-1,5,main]
Thread[pool-1-thread-1,1,main]|Thread[Thread-0,5,main]
Thread[pool-1-thread-4,1,main]|Thread[Thread-3,5,main]
Thread[pool-1-thread-3,1,main]|Thread[Thread-2,5,main]
Thread.join(threadA)方法的使用,它的作用是在线程A执行过程中挂起,让线程B执行,直到B被interrupt或者执行完毕
package threadtest; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class SleepTask extends Thread { private String name; public SleepTask(String name) { this.name = name; } public String getMyName() { return name; } @Override public void run() { System.out.println(name + ": begin to sleep"); try { TimeUnit.MILLISECONDS.sleep(2000); } catch (InterruptedException e) { System.out.println(name + " was interrupted"); return; } System.out.println(name + ": end sleep"); } public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { exec.execute(new SleepTask("Sleeper")); } exec.shutdown(); } } package threadtest; import java.util.concurrent.TimeUnit; public class JoinThread extends Thread { private String name; private SleepTask sleeper; public JoinThread(String name, SleepTask sleeper) { this.name = name; this.sleeper = sleeper; } @Override public void run() { try { System.out.println(name + ": waiting for sleeper: " + sleeper.getMyName()); TimeUnit.MILLISECONDS.sleep(100); // 有了join的介入,这个线程会挂起,必须等到sleeper线程执行完毕才能继续执行 // 除非sleeper线程执行了interrupt()方法 sleeper.join(); System.out.println(name + ": sleeper join end " + sleeper.getMyName() + ": " + sleeper.isAlive()); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { SleepTask sleeper = new SleepTask("sleeper1"); SleepTask sleeper2 = new SleepTask("sleeper2"); sleeper.start(); sleeper2.start(); (new JoinThread("join1", sleeper)).start(); (new JoinThread("join2", sleeper2)).start(); sleeper2.interrupt(); } }
sleeper1: begin to sleep
sleeper2: begin to sleep
join1: waiting for sleeper: sleeper1
sleeper2 was interrupted
join2: waiting for sleeper: sleeper2
join2: sleeper join end sleeper2: false
sleeper1: end sleep
join1: sleeper join end sleeper1: false
package threadtest; public class Accessor extends Thread { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { // 独立的本地存储数字 ThreadLocalVarHolder.increment(); System.out.println(this); Thread.yield(); } } @Override public String toString() { return Thread.currentThread() + "# id : " + ThreadLocalVarHolder.get(); } } package threadtest; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class ThreadLocalVarHolder { // 使用ThreadLocal,在线程使用他时会分配独立本地存储,互不干扰 private static ThreadLocal<Integer> value = new ThreadLocal<Integer>() { private Random rand = new Random(47); @Override protected Integer initialValue() { return rand.nextInt(1000); } }; public static void increment() { value.set(value.get() + 1); } public static int get() { return value.get(); } public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) exec.execute(new Accessor()); try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } exec.shutdownNow(); } }
Thread[pool-1-thread-1,5,main]# id : 259
Thread[pool-1-thread-2,5,main]# id : 556
Thread[pool-1-thread-3,5,main]# id : 694
Thread[pool-1-thread-2,5,main]# id : 557
Thread[pool-1-thread-2,5,main]# id : 558
Thread[pool-1-thread-2,5,main]# id : 559
Thread[pool-1-thread-3,5,main]# id : 695
Thread[pool-1-thread-2,5,main]# id : 560
Thread[pool-1-thread-3,5,main]# id : 696
Thread[pool-1-thread-2,5,main]# id : 561
Thread[pool-1-thread-2,5,main]# id : 562
Thread[pool-1-thread-3,5,main]# id : 697
Thread[pool-1-thread-2,5,main]# id : 563
Thread[pool-1-thread-3,5,main]# id : 698
Thread[pool-1-thread-2,5,main]# id : 564
Thread[pool-1-thread-3,5,main]# id : 699
Thread[pool-1-thread-2,5,main]# id : 565
Thread[pool-1-thread-3,5,main]# id : 700
Thread[pool-1-thread-2,5,main]# id : 566
Thread[pool-1-thread-3,5,main]# id : 701
Thread[pool-1-thread-2,5,main]# id : 567
Thread[pool-1-thread-3,5,main]# id : 702
Thread[pool-1-thread-2,5,main]# id : 568
Thread[pool-1-thread-3,5,main]# id : 703
Thread[pool-1-thread-2,5,main]# id : 569
Thread[pool-1-thread-3,5,main]# id : 704
后台线程:后台线程的效果是程序不会等待后台线程的执行,而是后台线程会随着程序的执行完毕而结束
package threadtest; import java.util.concurrent.TimeUnit; public class DaemonThreadTest { class MyThread extends Thread { @Override public void run() { // 注意此处 sleep() 的作用,他是为了让 main() 里的 print 先输出 try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread() + " : Thread run"); } } public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 5; i++) { Thread t = (new DaemonThreadTest()).new MyThread(); t.setDaemon(true); // 设置为后台线程 t.start(); } System.out.println("All daemons prepared"); // 如果将这句 sleep 注释掉,那么run方法里的打印将不会输出 // 这是因为 daemon 后台线程会随着 main 方法的结束而结束 TimeUnit.MILLISECONDS.sleep(1000); } }
All daemons prepared
Thread[Thread-1,5,main] : Thread run
Thread[Thread-2,5,main] : Thread run
Thread[Thread-0,5,main] : Thread run
Thread[Thread-3,5,main] : Thread run
Thread[Thread-4,5,main] : Thread run