一、submit与execute对比
- 新建测试线程,在run方法中打印线程名
package com.ykq;
/**
* 我的线程类
* @author YKQ
*/
public class MyThread implements Runnable{
public void run() {
// 打印当前线程名
System.out.println("当前线程名:" + Thread.currentThread().getName());
// 测试抛出异常
throw new RuntimeException();
}
}
- submit使用如下,可通过Future判断线程是否执行成功
package com.ykq;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecuteAndSubmit {
public static void main(String[] args) {
// 新建一个大小为3的定长线程池
ExecutorService ex= Executors.newFixedThreadPool(3);
for(int i = 0; i < 10 ; i++) {
MyThread myTread = new MyThread();
Future<?> result = ex.submit(myTread);
try {
// 判断执行成功的条件
if(result.get() == null) {
System.out.println(" 执行成功!");
} else {
Object o = result.get();
System.out.println(o.toString());
}
} catch (Exception e){
e.printStackTrace();
}
}
// 线程执行完,则关闭线程池
ex.shutdown();
}
}
- execute使用如下,无法判断线程执行成功或失败的情况,实际线程内部抛出了异常
package com.ykq;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecuteAndSubmit {
public static void main(String[] args) {
// 新建一个大小为3的定长线程池
ExecutorService ex= Executors.newFixedThreadPool(3);
for(int i = 0; i < 10 ; i++) {
MyThread myTread = new MyThread();
ex.submit(myTread);
}
// 线程执行完,则关闭线程池
ex.shutdown();
}
}
二、newFixedThreadPool的使用
定长线程池的使用
package com.ykq;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 定长线程池的使用
* @author YKQ
*/
public class FixedThreadPoolTest {
public static void main(String[] args) {
// 新建一个大小为3的定长线程池
ExecutorService ex= Executors.newFixedThreadPool(3);
for(int i = 0; i < 10 ; i++) {
MyThread myTread = new MyThread();
ex.submit(myTread);
}
// 线程执行完,则关闭线程池
ex.shutdown();
}
/**
* 我的线程类
* @author YKQ
*/
public static class MyThread implements Runnable{
public void run() {
// 打印当前线程名
System.out.println("当前线程名:" + Thread.currentThread().getName());
}
}
}
执行结果如下:从执行结果可看出总共有三个线程存在。
三、newCachedThreadPool的使用
当没有空闲的线程时,则新建一个线程。
package com.ykq;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 缓存线程池的使用
* @author YKQ
*/
public class CachedThreadPoolTest {
public static void main(String[] args) {
// 新建一个缓存线程池
ExecutorService ex= Executors.newCachedThreadPool();
for(int i = 0; i < 10 ; i++) {
MyThread myTread = new MyThread();
// 发现两个执行线程的方法,submit,execute
ex.submit(myTread);
}
// 线程执行完,则关闭线程池
ex.shutdown();
}
/**
* 我的线程类
* @author YKQ
*/
public static class MyThread implements Runnable{
public void run() {
// 打印当前线程名
System.out.println("当前线程名:" + Thread.currentThread().getName());
}
}
}
执行结果如下:当增加for循环的循环次数增大时,可见更多的线程被打印
三、newSingleThreadExecutor的使用
单个线程顺序执行
package com.ykq;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
1. 单线程的线程池
2. @author YKQ
*/
public class SingleThreadExecutorTest {
public static void main(String[] args) {
// 新建一个单线程的线程池
ExecutorService ex= Executors.newSingleThreadExecutor();
for(int i = 0; i < 10 ; i++) {
MyThread myTread = new MyThread();
ex.submit(myTread);
}
// 线程执行完,则关闭线程池
ex.shutdown();
}
/**
* 我的线程类
* @author YKQ
*/
public static class MyThread implements Runnable{
public void run() {
// 打印当前线程名
System.out.println("当前线程名:" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch(Exception e) {
}
}
}
}
执行结果如下:因为代码中执行了Thread.sleep(1000),在执行过程中可明显看出打印有间隔时间。
四、newScheduledThreadPool的使用
- 延时执行的定长线程池,执行完会结束
package com.ykq;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 定时线程池
*
* @author YKQ
*/
public class ScheduledThreadPoolTest {
public static void main(String[] args) {
// 新建一个定时定长的线程池
ScheduledExecutorService ex= Executors.newScheduledThreadPool(3);
for(int i = 0; i < 10 ; i++) {
MyThread myTread = new MyThread();
// 延迟5秒执行
ex.schedule(myTread, 5, TimeUnit.SECONDS);
}
ex.shutdown();
}
/**
* 我的线程类
* @author YKQ
*/
public static class MyThread implements Runnable{
public void run() {
// 打印当前线程名
System.out.println("当前线程名:" + Thread.currentThread().getName());
}
}
}
- 延时间隔循环执行的定长线程池,需要在线程内部手动判断停止线程,否则一直执行
package com.ykq;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 定时线程池
*
* @author YKQ
*/
public class ScheduledThreadPoolTest {
private static AtomicInteger time = new AtomicInteger(0);
public static void main(String[] args) {
// 新建一个定时线程池
ScheduledExecutorService ex= Executors.newScheduledThreadPool(3);
MyThread myTread = new MyThread(ex);
// 延迟5秒,间隔1秒循环执行
ex.scheduleWithFixedDelay(myTread, 5, 1, TimeUnit.SECONDS);
// 需要注释下面的暂停代码,否则线程停止
// ex.shutdown();
}
/**
* 我的线程类
* @author YKQ
*/
public static class MyThread implements Runnable{
private ScheduledExecutorService ex;
public MyThread(ScheduledExecutorService ex) {
this.ex = ex;
}
public void run() {
time.addAndGet(1);
// 打印当前线程名
System.out.println("当前线程名:" + Thread.currentThread().getName());
// 在代码里判断暂停逻辑,当执行10次时暂停
if(time.get() == 10) {
ex.shutdown();
}
}
}
}
还有一种单线程的定时线程池newSingleThreadScheduledExecutor,此处就不讲解了,等同于newScheduledThreadPool(1)