(1)继承Thread
public class test extends Thread{
@Override
public void run(){
System.out.println("创建成功了么");
}
public static void main(String[] args) {
test a=new test();
a.start();
}
}
(2)实现runable接口
public class test implements Runnable{
@Override
public void run(){
System.out.println("创建成功了么");
}
public static void main(String[] args) {
test a=new test();
new Thread(a).start();
}
}
(3)实现Callable接口
public class test implements Callable{
public static void main(String[] args) {
test a=new test();
FutureTask futureTask=new FutureTask<>(a);
new Thread(futureTask).start();
Object su=null;
try {
su=futureTask.get();
}catch (Exception e){
e.printStackTrace();
}
System.out.println(su);
}
@Override
public Boolean call() throws Exception {
return null;
}
}
上述三种方法可以用来创建线程,当然也可以通过线程池创建线程。下述为线程池ThreadPoolExecutor构造函数。Java中也提供了Executors工具类简化线程池的创建过程,但是由于粒度太大,可塑性不强,不推荐。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
上述代码中,包含了线程池创建的七大参数:核心线程数、最大线程数、阻塞队列、空闲线程存活时间、时间单位、创建线程的工程类、拒绝策略。具体示例如下:
ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread();
}
}, new ThreadPoolExecutor.AbortPolicy());
进入线程池的execute方法中:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//线程池的线程个数少于corePoolSize则创建新线程执行当前任务
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//线程个数大于corePoolSize或者创建线程失败,则将任务存放在阻塞队列workQueue中
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//如果当前任务无法放进阻塞队列中,则创建新的线程来执行任务
else if (!addWorker(command, false))
reject(command);
}
可以通过上述代码看出线程池中线程创建过程,对于许多面试题中提出:如果通过线程池知道一个线程是否已经完成。对于这个问题的解答,可以通过线程池的另一个运行方法submit(),此方法提供了一个Future的返回值,可以通过Future.get()方法获取任务的返回值。和execute相比,execute只能提交Runnable类型的任务,无返回值。submit既能提交Runnable类型的任务,返回值为null,也能提交Callable类型的任务,返回值为Future。如下所示
FutureTask futureTask1= (FutureTask) threadPoolExecutor.submit(new Callable() {
@Override
public Boolean call() throws Exception {
return null;
}
});
Object ob=futureTask1.get();
看到submit源码,其内部也会使用execute来创建。
public Future submit(Callable task) {
if (task == null) throw new NullPointerException();
RunnableFuture ftask = newTaskFor(task);
execute(ftask);
return ftask;
}