问问建设网站的人,南阳东莞网站建设公司,广州澄网站建设公司,网站开发和运营合同分开签么目录JDK8 创建的线程的两种方式orcle文档解释方式一#xff1a;继承Thread类方式二#xff1a;实现Runnable接口同时用两种的情况其他间接创建方式Callable接口线程池JDK8 创建的线程的两种方式
orcle文档解释
orcle文档#xff1a;https://docs.oracle.com/javase/8/docs…
目录JDK8 创建的线程的两种方式orcle文档解释方式一继承Thread类方式二实现Runnable接口同时用两种的情况其他间接创建方式Callable接口线程池JDK8 创建的线程的两种方式
orcle文档解释
orcle文档https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html 总结:
准确的讲创建线程只有一种方式那就是构造Thread类而实现线程的执行单元有两种方式
方法一实现Runnable接口的重写run方法并把Runnable实例传给Thread类方法二∶重写Thread的run方法继承Thread类)
(其他一些方式究其根本都是间接的通过上面两种方式创建的)
方式一继承Thread类
public static void main(String[] args) {System.out.println(主线程运行 Thread.currentThread().getName());Task1 task new Task1();task.start();}static class Task1 extends Thread{Overridepublic void run() {for (int i 0; i 20; i) {System.out.println(task1线程运行 Thread.currentThread().getName());System.out.println(Task11继承Thread实现多线程);}}}}自定义线程类继承Thread类 重写run()方法编写线程执行体 创建线程对象调用start()方法启动线程 方式二实现Runnable接口
public static void main(String[] args) {Task task new Task();Thread thread new Thread(task);thread.start();}static class Task implements Runnable{Overridepublic void run() {for (int i 0; i 20; i) {System.out.println(task1线程运行 Thread.currentThread().getName());System.out.println(Task11实现Runnable接口实现多线程);}}}定义MyRunnable类实现Runnable接口 实现run()方法编写线程执行体 创建线程对象调用start()方法启动线程 同时用两种的情况
public static void main(String[] args) {new Thread(new Runnable() {Overridepublic void run() {System.out.println(实现Runnable的run方法);}}){Overridepublic void run() {System.out.println(匿名内部类,重写Thread类的run方法);}}.run();
}结果
匿名内部类,重写Thread类的run方法分析
这里使用的匿名内部类在匿名内部类里面又重写了Thread类的run方法。创建Thread类的同时传入了Runnable对象这时候Thread类的run已被重写不再是原生方法的逻辑执行传入task的run 所以即便传入Runnable也不会被执行。
其他间接创建方式
Callable接口
public static void main(String[] args) {Task task new Task();FutureTaskInteger ft new FutureTask(task);Thread thread new Thread(ft);thread.start();}static class Task implements CallableInteger {Overridepublic Integer call() throws Exception {for (int i 0; i 20; i) {System.out.println(task1线程运行 Thread.currentThread().getName());System.out.println(Task11实现Callable接口实现多线程);}return 1;}
}FutureTask实现了RunnableFuture接口RunnableFuture继承了Runnable 和 Future接口。所以也是间接通过Runnable来创建的。 实现Callable接口需要返回值类型重写call方法需要抛出异常创建目标对象创建执行服务:ExecutorService ser Executors.newFixedThreadPool(1);提交执行:Future result1 ser.submit(t1);获取结果: boolean r1 result1.get()关闭服务: ser.shutdownNow(); 实现Runnable接口和Callable接口的区别 Runnable 接口不会返回结果Callable 接口可以返回结果Callable接口实现类中的run方法允许异常向上抛出可以在内部处理try catch但是runnable接口实现类中run方法的异常必须在内部处理不能抛出 线程池
ThreadPoolExecutor类的execute方法 public void execute(Runnable command) {if (command null)throw new NullPointerException();/** Proceed in 3 steps:** 1. If fewer than corePoolSize threads are running, try to* start a new thread with the given command as its first* task. The call to addWorker atomically checks runState and* workerCount, and so prevents false alarms that would add* threads when it shouldnt, by returning false.** 2. If a task can be successfully queued, then we still need* to double-check whether we should have added a thread* (because existing ones died since last checking) or that* the pool shut down since entry into this method. So we* recheck state and if necessary roll back the enqueuing if* stopped, or start a new thread if there are none.** 3. If we cannot queue task, then we try to add a new* thread. If it fails, we know we are shut down or saturated* and so reject the task.*/int c ctl.get();//如果工作线程数小于核心线程数if (workerCountOf(c) corePoolSize) {//执行addWorker,会创建一个核心线程如果创建失败重新获取ctlif (addWorker(command, true))return;c ctl.get();}//如果工作线程数大于等于核心线程数线程池的状态是RUNNING并且可以添加进队列//RUNNING状态下如果添加失败说明是队列已经满了接着就去创建新的线程如果大于最大线程数则执行拒绝策略//如果线程池不是RUNNING状态则执行拒绝策略当然还会调addWorker进行判断一次if (isRunning(c) workQueue.offer(command)) {//再次获取ctl进行双重检索也就是对线程池的状态再次检查一遍int recheck ctl.get();//如果线程池是不是处于RUNNING的状态那么就会将任务从队列中移除//如果移除失败则会判断工作线程是否为0 如果过为0 就创建一个非核心线程//如果移除成功就执行拒绝策略因为线程池已经不可用了if (! isRunning(recheck) remove(command))reject(command);else if (workerCountOf(recheck) 0)addWorker(null, false);}else if (!addWorker(command, false))//线程池挂了或者大于最大线程数reject(command);
}addWork方法会创建线程池内工作线程Worker。Worker这个线程实现了Runnable接口并持有一个线程thread一个初始化的任务firstTask。thread是调用构造方法时通过ThreadFactory来创建的线程 ThreadFactory中也是Runnable创建线程的模式。