详解三种java实现多线程的方式
java中实现多线程的方法有两种:继承Thread类和实现runnable接口。
1.继承Thread类,重写父类run()方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class thread1 extends Thread { public void run() { for ( int i = 0 ; i < 10000 ; i++) { System.out.println( "我是线程" + this .getId()); } } public static void main(String[] args) { thread1 th1 = new thread1(); thread1 th2 = new thread1(); th1.run(); th2.run(); } } |
run()方法只是普通的方法,是顺序执行的,即th1.run()执行完成后才执行th2.run(),这样写只用一个主线程。多线程就失去了意义,所以应该用start()方法来启动线程,start()方法会自动调用run()方法。上述代码改为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class thread1 extends Thread { public void run() { for ( int i = 0 ; i < 10000 ; i++) { System.out.println( "我是线程" + this .getId()); } } public static void main(String[] args) { thread1 th1 = new thread1(); thread1 th2 = new thread1(); th1.start(); th2.start(); } } |
通过start()方法启动一个新的线程。这样不管th1.start()调用的run()方法是否执行完,都继续执行th2.start()如果下面有别的代码也同样不需要等待th2.start()执行完成,而继续执行。(输出的线程id是无规则交替输出的)
2.实现runnable接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class thread2 implements Runnable { public String ThreadName; public thread2(String tName){ ThreadName = tName; } public void run() { for ( int i = 0 ; i < 10000 ; i++) { System.out.println(ThreadName); } } public static void main(String[] args) { thread2 th1 = new thread2( "线程A" ); thread2 th2 = new thread2( "线程B" ); th1.run(); th2.run(); } } |
和Thread的run方法一样Runnable的run只是普通方法,在main方法中th2.run()必须等待th1.run()执行完成后才能执行,程序只用一个线程。要多线程的目的,也要通过Thread的start()方法(注:runnable是没有start方法)。上述代码修改为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class thread2 implements Runnable { public String ThreadName; public thread2(String tName){ ThreadName = tName; } public void run() { for ( int i = 0 ; i < 10000 ; i++) { System.out.println(ThreadName); } } public static void main(String[] args) { thread2 th1 = new thread2( "线程A" ); thread2 th2 = new thread2( "Thread-B" ); Thread myth1 = new Thread(th1); Thread myth2 = new Thread(th2); myth1.start(); myth2.start(); } } |
3.使用ExecutorService、Callable、Future实现有返回结果的多线程(JDK5.0以后)
可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现传说中有返回结果的多线程了。下面提供了一个完整的有返回结果的多线程测试例子,在JDK1.5下验证过没问题可以直接使用。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
import java.util.concurrent.*; import java.util.Date; import java.util.List; import java.util.ArrayList; /** * 有返回值的线程 */ @SuppressWarnings ( "unchecked" ) public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println( "----程序开始运行----" ); Date date1 = new Date(); int taskSize = 5 ; // 创建一个线程池 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 创建多个有返回值的任务 List<Future> list = new ArrayList<Future>(); for ( int i = 0 ; i < taskSize; i++) { Callable c = new MyCallable(i + " " ); // 执行任务并获取Future对象 Future f = pool.submit(c); // System.out.println(">>>" + f.get().toString()); list.add(f); } // 关闭线程池 pool.shutdown(); // 获取所有并发任务的运行结果 for (Future f : list) { // 从Future对象上获取任务的返回值,并输出到控制台 System.out.println( ">>>" + f.get().toString()); } Date date2 = new Date(); System.out.println( "----程序结束运行----,程序运行时间【" + (date2.getTime() - date1.getTime()) + "毫秒】" ); } } class MyCallable implements Callable<Object> { private String taskNum; MyCallable(String taskNum) { this .taskNum = taskNum; } public Object call() throws Exception { System.out.println( ">>>" + taskNum + "任务启动" ); Date dateTmp1 = new Date(); Thread.sleep( 1000 ); Date dateTmp2 = new Date(); long time = dateTmp2.getTime() - dateTmp1.getTime(); System.out.println( ">>>" + taskNum + "任务终止" ); return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】" ; } } |
代码说明:
上述代码中Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。
总结:实现java多线程的2种方式,runable是接口,thread是类,runnable只提供一个run方法,建议使用runable实现
java多线程,不管如何,最终都需要通过thread.start()来使线程处于可运行状态。第三种方法是听群里的兄弟们介绍的,所以就百度补上了。
以上就是本文的全部内容,希望对大家的学习有所帮助。
详解三种java实现多线程的方式的更多相关文章
- 详解三种缓存过期策略LFU,FIFO,LRU(附带实现代码)
在学操作系统的时候,就会接触到缓存调度算法,缓存页面调度算法:先分配一定的页面空间,使用页面的时候首先去查询空间是否有该页面的缓存,如果有的话直接拿出来,如果没有的话先查询,如果页面空间没有满的时候, ...
- Spring事务之详解--三种实现方式
实现购买股票案例: 一.引入JAR文件: 二.开始搭建分层架构---创建账户(Account)和股票(Stock)实体类 Account: /* * 账户 */ public class Accoun ...
- Java 枚举(enum) 详解7种常见的用法
Java 枚举(enum) 详解7种常见的用法 来源 https://blog.csdn.net/qq_27093465/article/details/52180865 JDK1.5引入了新的类型— ...
- Java网络编程和NIO详解开篇:Java网络编程基础
Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...
- Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO
Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...
- 转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。
原文来自于:http://www.ituring.com.cn/article/128439 Windows下的PHP开发环境搭建——PHP线程安全与非线程安全.Apache版本选择,及详解五种运行模 ...
- Java网络编程和NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型
Java网络编程与NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型 知识点 nio 下 I/O 阻塞与非阻塞实现 SocketChannel 介绍 I/O 多路复用的原理 事件选择器与 ...
- 图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)
参考网址:图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS) - 51CTO.COM 深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath ...
- Android 之窗口小部件详解(三) 部分转载
原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...
随机推荐
- 牛客假日团队赛1 G.Superbull
链接: https://ac.nowcoder.com/acm/contest/918/G 题意: Bessie and her friends are playing hoofball in the ...
- groovy使用小记
下载groovy的sdk, 解压后设置GROOVY_HOME和PATH变量 http://groovy-lang.org/download.html 使用IDEA创建java项目勾选Groovy组件 ...
- (转)Linux 开机引导和启动过程详解
Linux 开机引导和启动过程详解 编译自:https://opensource.com/article/17/2/linux-boot-and-startup作者: David Both 原创:LC ...
- Hadoop TaskScheduler源码分析
TaskScheduler是MapReduce中的任务调度器.在MapReduce中,JobTracker接收JobClient提交的Job,将它们按InputFormat的划分以及其他相关配置,生成 ...
- arch安装软件提示包损坏
错误:lib32-libjpeg6-turbo: signature from "Colin Keenan <colinnkeenan@gmail.com>" is u ...
- matlab 常用函数(数学建模-复习)
常用函数 fscanf(fid, '%c', inf) -> 直接读取整个文件, 因为inf表示无穷 strtrim char(num): 将num转为ASCII字符 strtok(conten ...
- 超链接显示网站 A,访问后进入网站 B
#前端黑魔法# 出一个思考题:如何用最少的字符实现下图效果.即超链接显示网站 A,访问后进入网站 B. 当然这个是上古时代的黑魔法了,稍懂前端的都知道原理.所以这里只问最短的实现~ 一个简单的演示:( ...
- wow.js+animate.css——有趣的页面滚动动画
今天偶然间发现了一个使用特别简单的页面动画效果,还挺不错的,玩了一个上午,现在介绍一下这个滚动动画: 一.使用方法: 1.下载animate.css 2.下载wow.js 3.引用文件,像这样: &l ...
- mysql 5.7以上安装遇到的问题
参考地址: https://blog.csdn.net/u012278016/article/details/80455439 本人在window上安装mysql 5.7版本以上的mysql,出现很 ...
- javascript设计模式之中介者模式
/* * 小游戏演示中介者模式 * Home 按键 1 * Guest 按键 0 * 半分钟内看谁按下的次数多 * * 参与的对象: * 玩家 * 计分板 * 中介者 * * 中介者模式使对象之间松耦 ...