- 浏览: 390740 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (215)
- ubuntu (27)
- 虚拟机 (13)
- 数据库 (29)
- JAVA (40)
- 搜索 (23)
- 开发工具 (2)
- 产品 (2)
- 工具 (1)
- 应用服务器 (5)
- linux (17)
- log (1)
- 多线程 (3)
- 异常 (1)
- shell (6)
- 12306 ;互联网 (1)
- 持续集成&Hudson (4)
- js (1)
- JAVA OR-Map (1)
- 漏洞 (1)
- svn (1)
- MAVEN (3)
- 架构 (1)
- windows (1)
- json (1)
- web (3)
- jenkins (2)
- iptables (2)
- JAVA ssh (0)
- 项目管理 (1)
- tomcat (1)
- 安全 (1)
- 数据库 mysql (1)
- 性能 (1)
最新评论
-
sbwfgihc:
怎么用的啊,
<转>mysql 树查询语句 -
panghaoyu:
实现一个智能提示功能需要ajax、数据库、jsp/php、算法 ...
<转>Solr Suggest实现搜索智能提示 -
songsove:
请问您qq多少
solr 对拼音搜索和拼音首字母搜索的支持 -
panghaoyu:
实现一个智能提示功能需要ajax、数据库、jsp/php、算法 ...
<转>Solr Suggest实现搜索智能提示 -
norain1988:
这样就可以实现相关搜索了吗
solr 百度相关搜索类似功能的实现
原链接:http://heipark.iteye.com/blog/1156011
newFixedThreadPool
创建一个固定大小的线程池。
shutdown():用于关闭启动线程,如果不调用该语句,jvm不会关闭。
awaitTermination():用于等待子线程结束,再继续执行下面的代码。该例中我设置一直等着子线程结束。
- public class Test {
- public static void main(String[] args) throws IOException, InterruptedException {
- ExecutorService service = Executors.newFixedThreadPool(2);
- for (int i = 0; i < 4; i++) {
- Runnable run = new Runnable() {
- @Override
- public void run() {
- System.out.println("thread start");
- }
- };
- service.execute(run);
- }
- service.shutdown();
- service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
- System.out.println("all thread complete");
- }
- }
thread start
thread start
thread start
all thread complete
newScheduledThreadPool
这个先不说,我喜欢用spring quartz.
CyclicBarrier
假设有只有的一个场景:每个线程代表一个跑步运动员,当运动员都准备好后,才一起出发,只要有一个人没有准备好,大家都等待.
- import java.io.IOException;
- import java.util.Random;
- import java.util.concurrent.BrokenBarrierException;
- import java.util.concurrent.CyclicBarrier;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- class Runner implements Runnable {
- private CyclicBarrier barrier;
- private String name;
- public Runner(CyclicBarrier barrier, String name) {
- super();
- this.barrier = barrier;
- this.name = name;
- }
- @Override
- public void run() {
- try {
- Thread.sleep(1000 * (new Random()).nextInt(8));
- System.out.println(name + " 准备OK.");
- barrier.await();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (BrokenBarrierException e) {
- e.printStackTrace();
- }
- System.out.println(name + " Go!!");
- }
- }
- public class Race {
- public static void main(String[] args) throws IOException, InterruptedException {
- CyclicBarrier barrier = new CyclicBarrier(3);
- ExecutorService executor = Executors.newFixedThreadPool(3);
- executor.submit(new Thread(new Runner(barrier, "zhangsan")));
- executor.submit(new Thread(new Runner(barrier, "lisi")));
- executor.submit(new Thread(new Runner(barrier, "wangwu")));
- executor.shutdown();
- }
- }
zhangsan 准备OK.
lisi 准备OK.
lisi Go!!
zhangsan Go!!
wangwu Go!!
ThreadPoolExecutor
newFixedThreadPool生成一个固定的线程池,顾名思义,线程池的线程是不会释放的,即使它是Idle。这就会产生性能问题,比如如果线程池的大小为200,当全部使用完毕后,所有的线程会继续留在池中,相应的内存和线程切换(while(true)+sleep循环)都会增加。如果要避免这个问题,就必须直接使用ThreadPoolExecutor()来构造。可以像Tomcat的线程池一样设置“最大线程数”、“最小线程数”和“空闲线程keepAlive的时间”。
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
corePoolSize:池中所保存的线程数,包括空闲线程(非最大同时干活的线程数)。如果池中线程数多于 corePoolSize,则这些多出的线程在空闲时间超过 keepAliveTime 时将会终止。
maximumPoolSize:线程池中最大线程数
keepAliveTime:线程空闲回收的时间
unit:keepAliveTime的单位
workQueue:保存任务的队列,可以如下选择:
- 无界队列: new LinkedBlockingQueue<Runnable>();
- 有界队列: new ArrayBlockingQueue<Runnable>(8);你不想让客户端无限的请求吃光你的CPU和内存吧,那就用有界队列
handler:
当提交任务数大于队列size会抛出RejectedExecutionException,可选的值为:
- ThreadPoolExecutor.CallerRunsPolicy 等待队列空闲
- ThreadPoolExecutor.DiscardPolicy:丢弃要插入队列的任务
- ThreadPoolExecutor.DiscardOldestPolicy:删除队头的任务
关于corePoolSize和maximumPoolSize:
- public class Test {
- public static void main(String[] args) {
- BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
- ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.DAYS, queue);
- for (int i = 0; i < 20; i++) {
- final int index = i;
- executor.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(4000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(String.format("thread %d finished", index));
- }
- });
- }
- executor.shutdown();
- }
- }
原子变量(Atomic )
并发库中的BlockingQueue是一个比较好玩的类,顾名思义,就是阻塞队列。该类主要提供了两个方法put()和take(),前者将一个对象放到队列中,如果队列已经满了,就等待直到有空闲节点;后者从head取一个对象,如果没有对象,就等待直到有可取的对象。
下面的例子比较简单,一个读线程,用于将要处理的文件对象添加到阻塞队列中,另外四个写线程用于取出文件对象,为了模拟写操作耗时长的特点,特让线程睡眠一段随机长度的时间。另外,该Demo也使用到了线程池和原子整型(AtomicInteger),AtomicInteger可以在并发情况下达到原子化更新,避免使用了synchronized,而且性能非常高。由于阻塞队列的put和take操作会阻塞,为了使线程退出,在队列中添加了一个“标识”,算法中也叫“哨兵”,当发现这个哨兵后,写线程就退出。
- import java.io.File;
- import java.io.FileFilter;
- import java.util.concurrent.BlockingQueue;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.LinkedBlockingQueue;
- import java.util.concurrent.atomic.AtomicInteger;
- public class Test {
- static long randomTime() {
- return (long) (Math.random() * 1000);
- }
- public static void main(String[] args) {
- // 能容纳100个文件
- final BlockingQueue<File> queue = new LinkedBlockingQueue<File>(100);
- // 线程池
- final ExecutorService exec = Executors.newFixedThreadPool(5);
- final File root = new File("D:\\dist\\blank");
- // 完成标志
- final File exitFile = new File("");
- // 读个数
- final AtomicInteger rc = new AtomicInteger();
- // 写个数
- final AtomicInteger wc = new AtomicInteger();
- // 读线程
- Runnable read = new Runnable() {
- public void run() {
- scanFile(root);
- scanFile(exitFile);
- }
- public void scanFile(File file) {
- if (file.isDirectory()) {
- File[] files = file.listFiles(new FileFilter() {
- public boolean accept(File pathname) {
- return pathname.isDirectory() || pathname.getPath().endsWith(".log");
- }
- });
- for (File one : files)
- scanFile(one);
- } else {
- try {
- int index = rc.incrementAndGet();
- System.out.println("Read0: " + index + " " + file.getPath());
- queue.put(file);
- } catch (InterruptedException e) {
- }
- }
- }
- };
- exec.submit(read);
- // 四个写线程
- for (int index = 0; index < 4; index++) {
- // write thread
- final int num = index;
- Runnable write = new Runnable() {
- String threadName = "Write" + num;
- public void run() {
- while (true) {
- try {
- Thread.sleep(randomTime());
- int index = wc.incrementAndGet();
- File file = queue.take();
- // 队列已经无对象
- if (file == exitFile) {
- // 再次添加"标志",以让其他线程正常退出
- queue.put(exitFile);
- break;
- }
- System.out.println(threadName + ": " + index + " " + file.getPath());
- } catch (InterruptedException e) {
- }
- }
- }
- };
- exec.submit(write);
- }
- exec.shutdown();
- }
- }
CountDownLatch
从名字可以看出,CountDownLatch是一个倒数计数的锁,当倒数到0时触发事件,也就是开锁,其他人就可以进入了。在一些应用场合中,需要等待某个条件达到要求后才能做后面的事情;同时当线程都完成后也会触发事件,以便进行后面的操作。
CountDownLatch最重要的方法是countDown()和await(),前者主要是倒数一次,后者是等待倒数到0,如果没有到达0,就只有阻塞等待了。
一个CountDouwnLatch实例是不能重复使用的,也就是说它是一次性的,锁一经被打开就不能再关闭使用了,如果想重复使用,请考虑使用CyclicBarrier。
下面的例子简单的说明了CountDownLatch的使用方法,模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。
- import java.util.concurrent.CountDownLatch;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- public class Test {
- public static void main(String[] args) throws InterruptedException {
- // 开始的倒数锁
- final CountDownLatch begin = new CountDownLatch(1);
- // 结束的倒数锁
- final CountDownLatch end = new CountDownLatch(10);
- // 十名选手
- final ExecutorService exec = Executors.newFixedThreadPool(10);
- for (int index = 0; index < 10; index++) {
- final int NO = index + 1;
- Runnable run = new Runnable() {
- public void run() {
- try {
- begin.await();
- Thread.sleep((long) (Math.random() * 10000));
- System.out.println("No." + NO + " arrived");
- } catch (InterruptedException e) {
- } finally {
- end.countDown();
- }
- }
- };
- exec.submit(run);
- }
- System.out.println("Game Start");
- begin.countDown();
- end.await();
- System.out.println("Game Over");
- exec.shutdown();
- }
- }
使用Callable和Future实现线程等待
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- public class Test {
- public static void main(String[] args) throws InterruptedException, ExecutionException {
- System.out.println("start main thread");
- final ExecutorService exec = Executors.newFixedThreadPool(5);
- Callable<String> call = new Callable<String>() {
- public String call() throws Exception {
- System.out.println(" start new thread.");
- Thread.sleep(1000 * 5);
- System.out.println(" end new thread.");
- return "some value.";
- }
- };
- Future<String> task = exec.submit(call);
- Thread.sleep(1000 * 2);
- task.get(); // 阻塞,并待子线程结束,
- exec.shutdown();
- System.out.println("end main thread");
- }
- }
CompletionService
这个东西的使用上很类似上面的example,不同的是,它会首先取完成任务的线程。下面的参考文章里,专门提到这个,大家有兴趣可以看下,例子:
- import java.util.concurrent.Callable;
- import java.util.concurrent.CompletionService;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ExecutorCompletionService;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- public class Test {
- public static void main(String[] args) throws InterruptedException,
- ExecutionException {
- ExecutorService exec = Executors.newFixedThreadPool(10);
- CompletionService<String> serv =
- new ExecutorCompletionService<String>(exec);
- for (int index = 0; index < 5; index++) {
- final int NO = index;
- Callable<String> downImg = new Callable<String>() {
- public String call() throws Exception {
- Thread.sleep((long) (Math.random() * 10000));
- return "Downloaded Image " + NO;
- }
- };
- serv.submit(downImg);
- }
- Thread.sleep(1000 * 2);
- System.out.println("Show web content");
- for (int index = 0; index < 5; index++) {
- Future<String> task = serv.take();
- String img = task.get();
- System.out.println(img);
- }
- System.out.println("End");
- // 关闭线程池
- exec.shutdown();
- }
- }
Semaphore信号量
拿到信号量的线程可以进入代码,否则就等待。通过acquire()和release()获取和释放访问许可。下面的例子只允许5个线程同时进入执行acquire()和release()之间的代码
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Semaphore;
- public class Test {
- public static void main(String[] args) {
- // 线程池
- ExecutorService exec = Executors.newCachedThreadPool();
- // 只能5个线程同时访问
- final Semaphore semp = new Semaphore(5);
- // 模拟20个客户端访问
- for (int index = 0; index < 20; index++) {
- final int NO = index;
- Runnable run = new Runnable() {
- public void run() {
- try {
- // 获取许可
- semp.acquire();
- System.out.println("Accessing: " + NO);
- Thread.sleep((long) (Math.random() * 10000));
- // 访问完后,释放
- semp.release();
- } catch (InterruptedException e) {
- }
- }
- };
- exec.execute(run);
- }
- // 退出线程池
- exec.shutdown();
- }
- }
参考:
jdk1.5中的线程池使用简介
http://www.java3z.com/cwbwebhome/article/article2/2875.html
CAS原理
http://www.blogjava.net/syniii/archive/2010/11/18/338387.html?opt=admin
jdk1.5中java.util.concurrent包编写多线程
http://hi.baidu.com/luotoo/blog/item/b895c3c2d650591e0ef47731.html
ExecutorSerive vs CompletionService
http://www.coderanch.com/t/491704/threads/java/ExecutorSerive-vs-CompletionService
-- end --
相关推荐
Java.util.concurrent(JUC)是Java平台中的一个核心包,专门用于处理多线程并发问题。这个包包含了大量的工具类和接口,极大地简化了并发编程的复杂性,提高了程序的性能和可伸缩性。本测试源文件主要是针对JUC并发...
8. **并发编程改进**:包括`java.util.concurrent`包的引入,提供如`ExecutorService`、`Future`、`Semaphore`等高级并发工具,以及`synchronized`关键字的改进,如可中断的同步和更精确的锁定。 9. **NIO(New IO...
11. **并发编程改进**:`java.util.concurrent`包提供了线程池、并发集合和同步工具类,如`ExecutorService`、`Future`和`Semaphore`,帮助开发者更方便地编写并发程序。 以上是Java JDK 5.0的关键特性,这些改进...
1. java.util.concurrent包的扩展:新增了并发工具类,如ExecutorService、Future、Callable等,提供了强大的多线程处理能力。 2. NIO.2(New I/O 2):提供了一种新的I/O API,支持文件系统事件监听、异步I/O操作,...
Java提供了多种工具,如`synchronized`关键字、`java.util.concurrent`包,来保证线程安全。 12. **Java的安全API**:如`java.security`包中的API,包括密钥和证书管理,数字签名,消息摘要,随机数生成等,这些都...
12. **并发工具类(java.util.concurrent)**:包含如Semaphore、CountDownLatch、CyclicBarrier等高级并发控制工具,便于开发多线程应用。 通过《Java JDK 6 学习笔记》中的示例,读者可以深入了解这些特性,并...
11. **并发编程改进**:引入了java.util.concurrent包,提供了线程安全的数据结构和并发工具类,如ExecutorService、Semaphore等,使得多线程编程更加高效和易用。 12. **NIO(非阻塞I/O)**:Java 5.0引入了NIO...
在ConcurrentProgrammingStudyNotes中,你可能找到关于Java并发API的详细讲解,包括`java.util.concurrent`包下的Thread、Runnable、ExecutorService、Semaphore、CountDownLatch、CyclicBarrier、...
9. **并发改进**:Java 5.0引入了`java.util.concurrent`包,包含了丰富的并发工具类,如线程池(ExecutorService)、并发集合(ConcurrentHashMap、CopyOnWriteArrayList等)以及Future和Callable接口,大大简化了...
在API方面,Java 6添加了许多新类和接口,如`java.util.concurrent`包中的并发工具类,如`ExecutorService`,帮助开发者更好地处理多线程编程。还有`java.util.ServiceLoader`,方便加载和使用服务提供者接口。 总...
这份"Java JDK 6学习笔记——ppt简体版"提供了关于这个关键版本的详细教程,适合初学者和有一定经验的开发者来深入理解Java编程。 首先,我们要了解Java JDK是什么。Java Development Kit,简称JDK,是Oracle公司...
本学习笔记将聚焦于JDK 5.0的关键更新,旨在帮助开发者理解和掌握这个里程碑式的Java版本。 1. **类型注解 (Type Annotations)** JDK 5.0引入了泛型,允许在类、接口和方法声明中使用类型参数,提高了代码的类型...
同时,`java.util.concurrent`包提供了线程安全的集合类,如`ConcurrentHashMap`和`CopyOnWriteArrayList`,以支持多线程编程。 3. **异常处理**:Java的异常处理机制通过`try-catch-finally`块来捕获和处理错误。`...
7. **多线程**:理解Java多线程编程,包括Thread类的使用、Runnable接口、同步机制(synchronized关键字、wait/notify机制)、线程池的创建和管理,以及并发库java.util.concurrent的高级特性。 8. **网络编程**:...
11. **线程并发API**:JDK 5.0对多线程编程的支持有所增强,包括`java.util.concurrent`包,提供了如`ExecutorService`、`Future`、`Semaphore`等高级并发工具,简化了并发编程。 总的来说,《良葛格Java JDK 5.0...
引入了`java.util.concurrent`包,包含了许多线程安全的数据结构和并发工具类,如ExecutorService、Semaphore、CountDownLatch等,极大地简化了多线程编程。 通过深入学习这些JDK 5.0的新特性,你将能更好地理解和...