线程中断
// 向线程发送中断请求
void interrupt()
// 测试当前线程是否中断。这是一个静态方法,且这一调用会修改线程的中断状态
static boolean interrupted()
// 测试当前线程是否中断,且不修改线程的中断状态
boolean isInterrupted()
// 返回当前执行线程的Thread对象
static Thread currentThread()
线程状态
new、Runnable、Blocked、Waiting、Timed Waiting、Terminated
要确定一个线程的当前状态,可以调用getState方法。
线程同步
- 锁对象ReentrantLock类
myLock.lock();
try{
critical section
}
finally{
myLock.unlock();
}
条件对象
一个锁对象可以有一个或多个条件对象,可以用newCondition方法获得一个条件对象。当线程不满足条件时,调用await()进入等待,并释放锁,直到别的线程调用同一条件上的signalAll方法,这将激活所有因为这一条件而进入等待状态的线程。当锁重新可用时,这些等待线程中的某个将从await状态中返回,并重新获得该锁,并从被阻塞的地方继续执行。此时,线程应该重新测试改条件,确保条件得到了满足。
值得注意的是,调用signalAll不会立即激活一个等待线程,它仅仅是解除等待线程的阻塞状态,以便这些线程可以在当前线程退出同步方法之后,通过竞争实现对对象的访问。synchronized关键字—内部对象锁
内部锁和条件的局限:
- 不能中断一个正在试图获得锁的线程;
- 试图获得锁是不能设定超时;
- 每个锁仅有单一的条件,可能是不够的;
- 监视器
特性:
- 监视器是只包含私有域的类;
- 每个监视器类的对象都有一个相关的锁;
- 使用该锁对所有的方法进行加锁;
- 该锁可以有任意多个相关条件。
volatile
详见另一篇博客final变量
当变量被声明为final时,其他线程会在构造器完成构造之后才看到这个变量的值。如果不使用final,就不能保证其他线程看到的是accounts更新后的值,他们可能都只是看到null,而不是新构造的值。原子性
ThreadLocal
详见另一篇博客
阻塞队列
阻塞队列方法
package MyThread;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class BlockingQueueTest {
//生产者
public static class Producer implements Runnable{
private final BlockingQueue<Integer> blockingQueue;
private volatile boolean flag;
private Random random;
public Producer(BlockingQueue<Integer> blockingQueue) {
this.blockingQueue = blockingQueue;
flag=false;
random=new Random();
}
public void run() {
while(!flag){
int info=random.nextInt(100);
try {
blockingQueue.put(info);
System.out.println(Thread.currentThread().getName()+" produce "+info);
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void shutDown(){
flag=true;
}
}
//消费者
public static class Consumer implements Runnable{
private final BlockingQueue<Integer> blockingQueue;
private volatile boolean flag;
public Consumer(BlockingQueue<Integer> blockingQueue) {
this.blockingQueue = blockingQueue;
}
public void run() {
while(!flag){
int info;
try {
info = blockingQueue.take();
System.out.println(Thread.currentThread().getName()+" consumer "+info);
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void shutDown(){
flag=true;
}
}
public static void main(String[] args){
BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<Integer>(10);
Producer producer=new Producer(blockingQueue);
Consumer consumer=new Consumer(blockingQueue);
//创建5个生产者,5个消费者
for(int i=0;i<10;i++){
if(i<5){
new Thread(producer,"producer"+i).start();
}else{
new Thread(consumer,"consumer"+(i-5)).start();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
producer.shutDown();
consumer.shutDown();
}
}
线程池
一个线程池包含许多准备运行的空闲线程,将Runnable对象交给线程池,就会有一个线程调用run方法。当run方法退出时,线程不会死亡,而是在池中准备为下一个请求提供服务。同时,使用一个线程数“固定的”线程池,可以限制并发线程的总数。