一个简单的java线程池
来源:互联网 发布:unity3d 角色动作 编辑:程序博客网 时间:2024/05/29 09:54
import java.util.Vector;public class SimpleThreadPool { /* 线程池中的 Trhead 数量 */ private static final Integer NTHREADS = 3; /* 线程池实例 */ private static SimpleThreadPool threadPool; private Vector<PThread> pthreads = new Vector<>(); private Vector<Runnable> runnables = new Vector<>(); /* 初始化线程池 */ private SimpleThreadPool() { for (int i = 0; i < NTHREADS; ++i) pthreads.add(new PThread(i)); for (PThread pthread : pthreads) pthread.start(); } /* 简单的单例模式线程池 */ public static synchronized SimpleThreadPool getInstance() { if (threadPool == null) threadPool = new SimpleThreadPool(); return threadPool; } /* * 向线程池提交一个任务(runnable, 或task) * 并且唤醒池中的一个睡眠线程, * * 如果线程池中没有空闲线程, 这个notify信号将会"丢失". * 但是这不影响线程池的功能, * 因为当一个线程结束任务的时候, 它会主动检查任务队列(runnables), 以查看是否有挂起的任务 * * 这个地方, runnables.size() 实际上为我们提供了一个 "唤醒信号计数器", 里面记录了唤醒信号的数目, * 所以, 严格地说, 其实唤醒信号并不会丢失. * * 这是一种常见的多线程模式: * 1. 为唤醒信号提供一个计数器 * 2. 线程睡眠之前总是先检查唤醒信号计数器 */ public void submit(Runnable runnable) { synchronized (runnables) { System.out.printf("summit runnable %d.\n", ((SimpleRunnable)runnable).getID()); runnables.add(runnable); runnables.notify(); } } /* 线程池中的工作线程 * * 这些线程完成其任务后不会退出, 而是马不停蹄地执行任务队列(runnables)中的下一个任务, * 如果任务队列中没有任务, 那么此线程将主动睡眠, 直到新的任务到来, 并将其唤醒. */ class PThread extends Thread { private Integer id; public PThread(Integer id) { this.id = id; } @Override public void run() { Runnable runnable; /* * 如果要实现线程池的销毁功能, 请在线程池中额外实现一个变量, 比如disabled, * 然后将while(true)替换为while(!disabled); */ while (true) { synchronized (runnables) { /* * 被唤醒的工作线程将重新检查当初导致其阻塞的条件, * 考虑到以下过程, 这是非常必要的. * * 1. 线程0被创建, 发现runnables.empty()==ture, 睡眠 * 2. 一个任务, 比如任务0, 被插入到任务队列(runnables), 向睡眠的线程发送信号. * 3. 线程1被创建, 发现runnables.size()==1, 删除这个任务, 因为线程1随后就要执行这个任务 * 4. 线程0被第(2)步中的信号唤醒, 此时任务0已经被线程1执行. * * 考虑第(4)步, 如果线程0醒来后不检查 睡眠条件, 那么线程0再次执行任务0, 导致不可知的行为. */ while (runnables == null || runnables.isEmpty()) { try { System.out.printf("Thread#%d going to sleep.\n", id); runnables.wait(); } catch (InterruptedException ie) { } } runnable = runnables.remove(0); } /* 小细节: 在外部执行任务 */ System.out.printf("Thread#%d waking up with runnable#%d\n", id, ((SimpleRunnable)runnable).getID()); runnable.run(); } } } /* 测试 */ public static void main(String args[]) throws InterruptedException { Thread.sleep(100); for (int i = 0; i < 10; ++i) { SimpleThreadPool.getInstance().submit(new SimpleRunnable(i)); Thread.sleep(100); } } /* 测试 */ static class SimpleRunnable implements Runnable { private Integer id; public SimpleRunnable(Integer id) { this.id = id; } public Integer getID() { return id; } @Override public void run() { System.out.printf("Runnable #%d passing by.\n", id); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("Runnable #%d quit.\n", id); } }}
阅读全文
0 0
- 【java】一个简单的线程池
- 一个简单的JAVA线程池实例
- java 一个简单的线程池
- Java实现一个简单的线程池
- 一个简单的java线程池实现
- 一个简单的java线程池
- 一个简单的线程池(仿java的ScheduledFuture)
- 写的一个简单的java线程池
- 一个简单的线程池
- 一个简单的线程池
- 一个简单的线程池
- 一个简单的线程池
- 一个简单的线程池
- 一个简单的线程池
- 一个简单的线程池
- 一个简单的JAVA线程池(只是用实验)
- 一个简单的线程池实现(java版)
- 一个简单的线程池实现(java版)
- Android Butterknife 8.4.0 使用方法总结
- Android实现多进程方式及注意
- jacob word 转pdf
- 关于librtmp接收数据(接收网络电视的数据流)
- Javascript中异步编程之Promise
- 一个简单的java线程池
- sku商品表设计
- Android优化(1)--布局优化
- 索引的概念和创建索引例子
- warning C4996: “strcpy”被声明为否决的解决办法
- 阿里面试回来,想和Java程序员谈一谈
- JavaScript(4)
- 编写arp脚本抓取对应主机mac地址
- 抽象类和接口的区别以及使用场景