Java笔记(三)多线程

线程中断

// 向线程发送中断请求
void interrupt()
// 测试当前线程是否中断。这是一个静态方法,且这一调用会修改线程的中断状态
static boolean interrupted()
// 测试当前线程是否中断,且不修改线程的中断状态
boolean isInterrupted()
// 返回当前执行线程的Thread对象
static Thread currentThread()

线程状态

new、Runnable、Blocked、Waiting、Timed Waiting、Terminated
要确定一个线程的当前状态,可以调用getState方法。

线程同步

  1. 锁对象ReentrantLock类
myLock.lock(); 
try{
    critical section
}
finally{
    myLock.unlock();
}
  1. 条件对象
    一个锁对象可以有一个或多个条件对象,可以用newCondition方法获得一个条件对象。当线程不满足条件时,调用await()进入等待,并释放锁,直到别的线程调用同一条件上的signalAll方法,这将激活所有因为这一条件而进入等待状态的线程。当锁重新可用时,这些等待线程中的某个将从await状态中返回,并重新获得该锁,并从被阻塞的地方继续执行。此时,线程应该重新测试改条件,确保条件得到了满足。
    值得注意的是,调用signalAll不会立即激活一个等待线程,它仅仅是解除等待线程的阻塞状态,以便这些线程可以在当前线程退出同步方法之后,通过竞争实现对对象的访问。

  2. synchronized关键字—内部对象锁
    内部锁和条件的局限:

  • 不能中断一个正在试图获得锁的线程;
  • 试图获得锁是不能设定超时;
  • 每个锁仅有单一的条件,可能是不够的;
  1. 监视器
    特性:
  • 监视器是只包含私有域的类;
  • 每个监视器类的对象都有一个相关的锁;
  • 使用该锁对所有的方法进行加锁;
  • 该锁可以有任意多个相关条件。
  1. volatile
    详见另一篇博客

  2. final变量
    当变量被声明为final时,其他线程会在构造器完成构造之后才看到这个变量的值。如果不使用final,就不能保证其他线程看到的是accounts更新后的值,他们可能都只是看到null,而不是新构造的值。

  3. 原子性

  4. 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方法退出时,线程不会死亡,而是在池中准备为下一个请求提供服务。同时,使用一个线程数“固定的”线程池,可以限制并发线程的总数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。