13-信号量和线程池
信号量
信号量这个词对于计算机专业的人并不陌生,因为这个词是计算机操作系统多道程序设计中很关键很重要的词。
抽象的来讲,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程/进程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。
在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。当一个线程调用Wait操作时,它要么得到资源然后将信号量减一,要么一直等下去(指放入阻塞队列),直到信号量大于等于一时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为释放了由信号量守护的资源。
在Java并发设计中,也存在信号量这个词。信号量为多线程协作提供了更为强大的控制。无论是什么锁,一次只允许一个线程访问,而信号量一次可以让多个线程访问。
public class Main implements Runnable{
public static void main(String[] args){
ExecutorService executorService= Executors.newFixedThreadPool(5);
Main main=new Main();
for(int i=0;i<20;i++){
executorService.submit(main);
}
}
Semaphore semaphore=new Semaphore(2);
public void run() {
try {
semaphore.acquire();
Thread.sleep(3000);
System.out.println(Thread.currentThread().getId());
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在上述程序中Semaphore semaphore=new Semaphore(2);这一句是new一个一次可以让2个线程访问的信号量。semaphore.acquire();用来尝试获得资源,如果获得了资源就立即执行。semaphore.release();用来释放资源,当一个任务执行完毕之后就应该释方资源,这里还用到了线程池,这个知识点一会会讲解。
线程池
上一个程序中使用到了线程池。
我们知道,进程的创建的杀死都需要耗费一定的资源,采用线程就是因为线程耗费的资源较少,然而线程在创建和杀死的时候也同样会耗费资源,特别是在程序中需要频繁的这么做的时候,会浪费大量的资源。最形象的例子就是数据库的连接池,在连接数据库的时候设置了连接池用来节约和控制资源。
我们在来看一下刚刚的程序有关于线程池的关键部分:
ExecutorService executorService= Executors.newFixedThreadPool(5);
Main main=new Main();
for(int i=0;i<20;i++){
executorService.submit(main);
}
ExecutorService executorService= Executors.newFixedThreadPool(5)这一句是用来创建一个线程池,这个线程池里的参数代表了线程池允许运行最大的线程数量。所以这里的5代表了允许有5个线程。
executorService.submit(main)这个方法可以调用类中的run方法,无论他是Thread中的run还有Runnable接口中的run方法。
上一篇: 线程池和信号量