实现多线程的三种方式:
ExecutorService pool = Executors.newFixedThreadPool(5); //创建线程池
MyCallable my = new MyCallable();
Future f = pool.submit(my);
Object o = f.get(); //获取call返回的对象
多线程的中断机制
多线程的同步机制
public synchronized void print(){
//程序逻辑
}
2、使用 synchronized修饰的程序块 ,第一种方法的锁只能是当前对象(this),而使用第二种方式可以使用任意的对象作为锁 。
public void print(){
synchronized(this){
//程序逻辑
}
}
锁对象可以调用wait方法来释放当前的锁的对象,线程会进入阻塞状态,只有通过其它拥有该锁的对象调用notify或notifyAll才能唤醒该线程,如果没有线程调用notify/notifyAll 方法则该线程将一直处于阻塞状态 。
锁对象也可以调用notify/notifyAll 方法来唤醒处于wait状态的线程,但是不是调用 notify/notifyAll后就会立即释放锁资源,而是在当前同步方法或者同步代码块执行完才会释放对象锁。
Java中的线程池
1、newFixedThreadPool 创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中,如下代码所示,线程池最多只能允许三个任务线程同时执行。
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i=0; i<10; i++){
pool.execute(new Thread());
}
2、newCachedThreadPool 创建一个可缓存的线程池,
1).工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
2).如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
ExecutorService pool = Executors.newCachedThreadPool();
for (int i=0; i<10; i++){
pool.execute(new Thread());
}
ExecutorService pool = Executors.newSingleThreadExecutor();
for (int i=0; i<10; i++){
pool.execute(new Thread());
}
4、newScheduleThreadPool 创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
for (int i=0; i<10; i++){
pool.schedule(new Thread(),3,TimeUnit.SECONDS);
}
结合Spring使用线程池
1、ThreadPoolTaskExecutor配置文件
1 <!-- spring thread pool executor -->
2 <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
3 <!-- 线程池维护线程的最少数量 -->
4 <property name="corePoolSize" value="5" />
5 <!-- 允许的空闲时间 -->
6 <property name="keepAliveSeconds" value="200" />
7 <!-- 线程池维护线程的最大数量 -->
8 <property name="maxPoolSize" value="10" />
9 <!-- 缓存队列 -->
10 <property name="queueCapacity" value="20" />
11 <!-- 对拒绝task的处理策略 -->
12 <property name="rejectedExecutionHandler">
13 <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
14 </property>
15 </bean>
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
2、java代码
1 @RunWith(SpringJUnit4ClassRunner.class)
2 @ContextConfiguration(classes = { MultiThreadConfig.class })
3 public class MultiThreadTest {
4
5 @Autowired
6 private ThreadPoolTaskExecutor taskExecutor;
7
8 @Autowired
9 private MultiThreadProcessService multiThreadProcessService;
10
11 @Test
12 public void test() {
13
14 int n = 20;
15 for (int i = 0; i < n; i++) {
16 taskExecutor.execute(new MultiThreadDemo(multiThreadProcessService));
17 System.out.println("int i is " + i + ", now threadpool active threads totalnum is " + taskExecutor.getActiveCount());
18 }
19
20 try {
21 System.in.read();
22 } catch (IOException e) {
23 throw new RuntimeException(e);
24 }
25 }
26 }