进程与线程:
一个进程可以包含多个线程。多个线程可以并行,但是一个时间点只能有一个线程是运行状态。
线程的状态:
查看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
先上代码:
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()方法。
这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
package com.my.thread; import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ThreadCycleBarrire {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CyclicBarrier cb = new CyclicBarrier(3); // 三个线程同时到达
for (int i = 0; i < 3; i++) {
Runnable runnable = new Runnable() {
public void run() {
try {
// Thread.sleep((long) (Math.random() * 10000));
System.out.println(
"线程" + Thread.currentThread().getName() + "即将到达集合地点1,当前已有" + (cb.getNumberWaiting() + 1)
+ "个已到达" + (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
try {
cb.await();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread.sleep((long) (Math.random() * 10000));
System.out.println(
"线程" + Thread.currentThread().getName() + "即将到达集合地点2,当前已有" + (cb.getNumberWaiting() + 1)
+ "个已到达" + (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
try {
cb.await();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread.sleep((long) (Math.random() * 10000));
System.out.println(
"线程" + Thread.currentThread().getName() + "即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1)
+ "个已到达" + (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
try {
cb.await();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
service.execute(runnable);
}
service.shutdown();
}
}
ThreadCycleBarrire.java
CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。
CyclicBarrier 可用于综合统计,用CyclicBarrier(int num,Runable run),最后运行run里面的方法。