当前位置:
首页 > temp > 简明python教程 >
-
Java 并发与多线程(2)
void put()
{
if (num < space)//有空位可放,可以生产
{
num++;
System.out.println("放入一个商品,现有" + num + "个商品," + (space - num) + "个空位");
notify();//唤醒等待该锁的线程
}
else//无空位可放,等待空位
{
try
{
System.out.println("没有空位可放,等待拿出");
wait();//进入该锁对象的等待池
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public synchronized void take()
{
if (num > 0)//有商品可拿
{
num--;
System.out.println("拿出一个商品,现有" + num + "个商品," + (space - num) + "个空位");
notify();//唤醒等待该锁的线程
}
else///等待生产产品
{
try
{
System.out.println("没有商品可拿,等待放入");
wait();//进入该锁对象的等待池
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
print
没有商品可拿,等待放入
放入一个商品,现有1个商品,9个空位
放入一个商品,现有2个商品,8个空位
拿出一个商品,现有1个商品,9个空位
放入一个商品,现有2个商品,8个空位
放入一个商品,现有3个商品,7个空位
放入一个商品,现有4个商品,6个空位
拿出一个商品,现有3个商品,7个空位
放入一个商品,现有4个商品,6个空位
···
线程池
线程的启动和结束都是比较消耗时间和占用资源的,如果在系统中用到了很多的线程,大量的启动和结束动作会严重影响性能
线程池很像生产者消费者模式,消费的对象是一个一个的能够运行的任务
-
设计思路
- 准备任务容器,可用 List,存放任务
- 线程池类构造方法中创建多个执行者线程
- 任务容器为空时,所有线程 wait
- 当外部线程向任务容器加入任务,就会有执行者线程被 notify
- 执行任务完毕后,没有接到新任务,就回归等待状态
-
实现一个线程池
public class ThreadPool { int poolSize;// 线程池大小 LinkedList<Runnable> tasks = new LinkedList<Runnable>();// 任务容器 public ThreadPool(int poolSize) { this.poolSize = poolSize; synchronized (tasks)//启动 poolSize 个任务执行者线程 { for (int i = 0; i < poolSize; i++) { new ExecuteThread("执行者线程 " + i).start(); } } } public void add(Runnable r)//添加任务 { synchronized (tasks) { tasks.add(r); System.out.println("加入新任务"); tasks.notifyAll();// 唤醒等待的任务执行者线程 } } class ExecuteThread extends Thread//等待执行任务的线程 { Runnable task; public ExecuteThread(String name) { super(name); } public void run() { System.out.println("启动:" + this.getName()); while (true) { synchronized (tasks) { while (tasks.isEmpty()) { try { tasks.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } task = tasks.removeLast(); tasks.notifyAll(); // 允许添加任务的线程可以继续添加任务 } System.out.println(this.getName() + " 接到任务"); task.run();//执行任务 } } } public static void main(String[] args) { ThreadPool pool = new ThreadPool(3); for (int i = 0; i < 5; i++) { Runnable task = new Runnable()//创建任务 { public void run()//任务内容 { System.out.println(Thread.currentThread().getName()+" 执行任务"); } }; pool.add(task);//加入任务 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
print
main 加入新任务 启动:执行者线程 0 执行者线程 0 接到任务 执行者线程 0 执行任务 启动:执行者线程 1 启动:执行者线程 2 main 加入新任务 执行者线程 2 接到任务 执行者线程 2 执行任务 main 加入新任务 执行者线程 2 接到任务 执行者线程 2 执行任务
-
java 线程池类
-
默认线程池类 ThreadPoolExecutor 在 java.util.concurrent 包下
ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); /* 第一个参数 int 类型, 10 表示这个线程池初始化了 10 个线程在里面工作 第二个参数 int 类型, 15 表示如果 10 个线程不够用了,就会自动增加到最多 15个 线程 第三个参数 60 结合第四个参数 TimeUnit.SECONDS,表示经过 60 秒,多出来的线程还没有接到任务,就会回收,最后保持池子里就 10 个 第五个参数 BlockingQueue 类型,new LinkedBlockingQueue() 用来放任务的集合 */
-
execute() 方法添加新任务
public class TestThread { public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); threadPool.execute(new Runnable() {//添加任务 public void run() { System.out.println("执行任务"); } }); } }
-
-
java 中几种线程池
java 线程池的顶级接口是 Executor ,子接口是 ExecutorService ,子接口使用更广泛
Executors 类提供了一系列工厂方法用于创建线程池,返回的线程池实现了 ExecutorService 接口
- newCachedThreadPool有缓冲的线程池,线程数 JVM 控制,有线程可使用时不会创建新线程
- newFixedThreadPool,固定大小的线程池,任务量超过线程数时,任务存入等待队列
- newScheduledThreadPool,创建一个线程池,可安排在给定延迟后运行命令或者定期地执行
- newSingleThreadExecutor,只有一个线程,顺序执行多个任务,若意外终止,则会新创建一个
ExecutorService threadPool = null; threadPool = Executors.newCachedThreadPool();//缓冲线程池 threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池 threadPool = Executors.newScheduledThreadPool(2);//定时任务线程池 threadPool = Executors.newSingleThreadExecutor();//单线程的线程池 threadPool = new ThreadPoolExecutor(···);//默认线程池,多个可控参数
线程安全类
- StringBuffer:内部方法用 synchronized 修饰
- Vetort:继承于 AbstractList
- Stack:继承于 Vector
- HashTable:继承于 Dictionary,实现了 Map 接口
- Property:继承于 HashTable,实现了 Map 接口
- concurrentHashMap:分段加锁机制
作者: pgjett
出处: https://pgjett.cnblogs.com
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程
检测数据类型的四种方法
js中数组的方法,32种方法
前端操作方法
数据类型
window.localStorage.setItem 和 localStorage.setIte
如何完美解决前端数字计算精度丢失与数