进程与线程:
一个进程可以包含多个线程。多个线程可以并行,但是一个时间点只能有一个线程是运行状态。
线程的状态:
查看API可以,线程的状态分为五种:
(JVM里面的状态:These states are virtual machine states which do not reflect any operating system thread states)
1. NEW: 当新建一个Thread的时候,当前线程的处于新建状态,线程还未开始。
2. RUNNABLE: 调用Thread的start方法,线程进入可运行状态,在这个状态下,线程开始处理工作,还有一种情况是未真正处理,还正在等待操作系统的调用。
3. BLOCKED: 线程的阻塞状态。一种情况下当调用wait方法时,当前线程释放锁,其他线程获取锁,开始处理,当前线程进入阻塞状态。
4. WAITING: 不定期等待状态。等待其他线程的notify.
5. TIMED_WAITING:有一定期限的等待状态,与WAITING最明显的区别是Thread.sleep(). 可以指定sleep时间。
6. TERMINATED: 终止状态。线程处理完成。
两个JDK自带的同步工具类:CountDownLatch 和CyclicBarrier
先上代码:
代码语言:javascript复制package com.my.thread;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchTest {
static CountDownLatch latch = new CountDownLatch(1);
static CountDownLatch downLatch = new CountDownLatch(10);
static ExecutorService service = Executors.newCachedThreadPool();
public static void main(String[] args) {
final long start = System.currentTimeMillis();
for (int i = 0; i < 10; i ) {
final int index = i 1;
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
latch.await();
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() "===已鸣枪,第" index "位运动员出发,反应时间:" (end-start) "ms");
Thread.sleep((long) (Math.random() * 10000));
end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() "===第" index "位运动员完成,用时" (end-start) "ms");
downLatch.countDown();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
service.execute(runnable);
}
try {
System.out.println("鸣枪开始!");
latch.countDown();
downLatch.await();
System.out.println("比赛结束");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
service.shutdown();
}
}
CountDownLatchTest .java
构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。
与CountDownLatch的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。
这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
代码语言:javascript复制 1 package com.my.thread;
2
3 import java.util.concurrent.BrokenBarrierException;
4 import java.util.concurrent.CyclicBarrier;
5 import java.util.concurrent.ExecutorService;
6 import java.util.concurrent.Executors;
7
8 public class ThreadCycleBarrire {
9 public static void main(String[] args) {
10 ExecutorService service = Executors.newCachedThreadPool();
11 final CyclicBarrier cb = new CyclicBarrier(3); // 三个线程同时到达
12 for (int i = 0; i < 3; i ) {
13 Runnable runnable = new Runnable() {
14 public void run() {
15 try {
16 // Thread.sleep((long) (Math.random() * 10000));
17 System.out.println(
18 "线程" Thread.currentThread().getName() "即将到达集合地点1,当前已有" (cb.getNumberWaiting() 1)
19 "个已到达" (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
20 try {
21 cb.await();
22 } catch (BrokenBarrierException e) {
23 // TODO Auto-generated catch block
24 e.printStackTrace();
25 }
26 Thread.sleep((long) (Math.random() * 10000));
27 System.out.println(
28 "线程" Thread.currentThread().getName() "即将到达集合地点2,当前已有" (cb.getNumberWaiting() 1)
29 "个已到达" (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
30 try {
31 cb.await();
32 } catch (BrokenBarrierException e) {
33 // TODO Auto-generated catch block
34 e.printStackTrace();
35 }
36 Thread.sleep((long) (Math.random() * 10000));
37 System.out.println(
38 "线程" Thread.currentThread().getName() "即将到达集合地点3,当前已有" (cb.getNumberWaiting() 1)
39 "个已到达" (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
40 try {
41 cb.await();
42 } catch (BrokenBarrierException e) {
43 // TODO Auto-generated catch block
44 e.printStackTrace();
45 }
46 } catch (InterruptedException e) {
47 // TODO Auto-generated catch block
48 e.printStackTrace();
49 }
50 }
51 };
52 service.execute(runnable);
53 }
54 service.shutdown();
55 }
56 }
CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。
CyclicBarrier 可用于综合统计,用CyclicBarrier(int num,Runable run),最后运行run里面的方法。