1.做一个线程池的工具类(最简单的)
package cn.xdf.wlyy.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPool {
// 单例,让池子只有一个
private ThreadPool() {
};
private static ThreadPool tp;
public static ThreadPool getInstance() {
if (tp == null) {
tp = new ThreadPool();
}
return tp;
}
// 构造一个任务池
// 参数说明:
// corePoolSize - 池中所保存的线程数,包括空闲线程。
// maximumPoolSize - 池中允许的最大线程数。
// keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
// unit - keepAliveTime 参数的时间单位。
// workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。
// threadFactory - 执行程序创建新线程时使用的工厂。
// handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(5));
// 在池子里取一个线程执行任务
public void execute(Runnable task) {
executor.execute(task);
}
public void shutdown() {
executor.shutdown();
}
}
2.看是否需要返回值,不需要的话就实现Runnable接口,重写run方法;需要的话就要实现Callable接口,重写call方法。而run与call方法中是我们要多线程的业务代码
2.1不需要返回用这个类
package cn.xdf.wlyy.thread;
import cn.xdf.wlyy.util.DateUtil;
public class TestTask implements Runnable {
//如果我们的任务需要一些数据,可以通过构造方法传进来
String param;
public TestTask(String param){
this.param = param;
}
public void run() {
System.out.println("正在执行task "+param + "," + DateUtil.getDateTime());
try {
Thread.currentThread().sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task "+param+"执行完毕," + DateUtil.getDateTime());
}
public static void main(String args[]){
for(int i=0;i<15;i++){
//得到我们的池子
ThreadPool tp = ThreadPool.getInstance();
//将我们的任务new出来
TestTask tt = new TestTask(i + "");
//用池子执行任务
tp.execute(tt);
}
}
}
2.2需要返回的话用这个类
package cn.xdf.wlyy.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import cn.xdf.wlyy.util.DateUtil;
public class TestCallble implements Callable<String> {
// 如果我们的任务需要一些数据,可以通过构造方法传进来
String param;
public TestCallble(String param) {
this.param = param;
}
@Override
public String call() throws Exception {
System.out.println("正在执行task " + param + "," + DateUtil.getDateTime());
try {
System.out.println(Thread.currentThread().getName());
Thread.currentThread().sleep(4000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task " + param + "执行完毕," + DateUtil.getDateTime());
return param;
}
public static void main(String args[]) {
for (int i = 0; i < 15; i++) {
// 得到我们的池子
ThreadPool tp = ThreadPool.getInstance();
// 将我们的任务new出来
TestCallble tt = new TestCallble(i + "");
FutureTask<String> dbtask = new FutureTask<String>(tt);
// 用池子执行任务
tp.execute(dbtask);
// 在这里可以做别的任何事情
String result = null;
try {
// 取得结果,同时设置超时执行时间为1秒。同样可以用future.get(),不设置执行超时时间取得结果
result = dbtask.get(3000, TimeUnit.MILLISECONDS);
// result = dbtask.get();
}
catch (Exception e) {
dbtask.cancel(true);
// 超时后,进行相应处理
}
finally {
System.out.println("task@" + i + ":result=" + result);
}
}
}
}
值得说明的事,如果要返回值的话,只需调用futureTask.get()方法(可以设置等待时间),但如果添加了这个,那么call中的sleep必然要等,形成阻塞,一条条的获取调用结果值。而如果不加的话,就跟run方法一样,例如ThreadPoolExecutor中的参数corePoolSize(核心线程数)为5,正常来说5次一起执行,但加了get方法只能一次次执行。失去了多线程的意义了。
我也是初学,还在找解决办法...