【Java】多线程相关复习—— 线程的创建、名字、运行情况以及顺序控制(join方法) 【一】
· 继承Thread类
· 实现Runnable接口
· 实现Callable接口
· 线程名字 getName()
· 线程活动情况 isAlive()
· 控制线程运行次序 join()
一、 创建线程的三种方式
① 继承Thread类
/**
* 步骤:
* 继承Thread重写run方法,创建该线程实例,调用start()方法启动线程
* @author ChristineBassoon
*
*/
public class test {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
} } class MyThread extends Thread{ @Override
public void run() {
for(int i=0;i<50;i++) {
System.out.println(i+"["+this.getName()+"]");
}
}
}
同种方法以匿名内部类形式
new Thread(){
@Override
public void run() {
for(int i=0;i<50;i++) {
System.out.println(i+"["+Thread.currentThread().getName()+"]");
}
}
}.start();
② 实现Runnable接口
/**
* 步骤:
* 实现Runnable接口,重写run方法,以此Runnable实例作为Thread的target创建Thread对象
* 调用start方法启动线程
* @author ChristineBassoon
*
*/
public class test {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
}
} class MyRunnable implements Runnable{ @Override
public void run() {
for(int i=0;i<50;i++) {
System.out.println(i+"["+Thread.currentThread().getName()+"]");
}
}
} //匿名内部类形式
new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<50;i++) {
System.out.println(i+"["+Thread.currentThread().getName()+"]");
}
}
}).start();
}
③ Callable方式
/**
* 步骤:
* 1. 实现Callable接口,使用FutureTask类来包装Callable对象
* 2. FutureTaskd对象作为Thread对象的target创建并启动线程
* (FutureTask同时实现了Runnable和Callable接口,所以能作为Thread对象的的target)
* 3. FutureTask的get()方法在子线程结束后可获得返回值(以此判断线程能否正常运行)
*/
public class test {
public static void main(String[] args) { CallableThread ct = new CallableThread();
FutureTask ft = new FutureTask<>(ct);
new Thread(ft).start();
try {
System.out.println("子线程返回值为:"+ft.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
} } class CallableThread implements Callable { @Override
public Integer call() throws Exception {
for(int i=0;i<50;i++) {
System.out.println(i+"["+Thread.currentThread().getName()+"]");
}
return 1;
}
}
二、线程状态
线程的几个状态可用图概括 (图源自google image),解释得非常清楚
//获取当前线程的名字
Thread.currentThread().getName();
//判断当前线程运行情况
Thread.currentThread().isAlive();
//设定线程的名字
Thread.currentThread().setName("");
//只有该线程结束后,程序才会向下进行
[new Thread()].join();//[]表示某线程
① 获取当前线程名字 —— getName()
情况1,获取主线程名字
public class ThreadTest {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()); }
}
结果为
main
情况2:获取子线程名字
new Thread() {
@Override
public void run(){
for(int i=0;i<5;i++) {
System.out.println(i+"["+Thread.currentThread().getName()+"]");
System.out.println(i+"["+this.getName()+"]");
}
}
}.start();
结果为
0[Thread-0]
0[Thread-0]
1[Thread-0]
1[Thread-0]
2[Thread-0]
2[Thread-0]
3[Thread-0]
3[Thread-0]
4[Thread-0]
4[Thread-0]
可看出,子程序运行期间,当前的线程( Thread.currentThread() )名字就是子程序的线程名。
②线程运行情况,判断线程是否在运行当中—— isAlive()
public class ThreadTest {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
System.out.println("");
try {
myThread.join();//确保子线程结束后才执行下方语句
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("");
System.out.println("myThread线程运行情况:"+myThread.isAlive());
}
} class MyThread extends Thread { public MyThread(){
System.out.println("====构造函数开始====");
System.out.println(this.isAlive());
System.out.println("====构造函数结束====");
} @Override
public void run(){
System.out.println("=====run开始======");
System.out.println(this.isAlive());
System.out.println("=====run结束======");
}
}
结果为:
====构造函数开始====
false
====构造函数结束==== =====run开始======
true
=====run结束====== myThread线程运行情况:false
总结:子线程只有调用start()方法后才会运行。
③ 线程之间的运行顺序 —— join() 方法的调控
接下来我们实验一下:
public class condition {
public static void main(String[] args) { MyThread myThread = new MyThread();
myThread.setName("子线程");//设定子线程名字
myThread.start();
System.out.println();
System.out.println("主线程运行完毕");
}
} class MyThread extends Thread { @Override
public void run(){
for(int i=0;i<20;i++) {
System.out.println(i+"["+this.getName()+"]");
}
}
}
结果:
主线程运行完毕
0[子线程]
1[子线程]
2[子线程]
3[子线程]
4[子线程]
5[子线程]
6[子线程]
7[子线程]
8[子线程]
9[子线程]
10[子线程]
11[子线程]
12[子线程]
13[子线程]
14[子线程]
15[子线程]
16[子线程]
17[子线程]
18[子线程]
19[子线程]
如果按照执行次序,本来应该最后打印的内容应该最后显示的,现在却放在最前头了。事实上,线程之间会互相争夺cpu资源,谁先抢到谁执行,像上述这种情况,则是主线程先抢到了cpu资源。如果必须保证先执行子线程,最后再执行主线程的打印动作的话,可以使用 join() 方法控制线程之间的执行次序。
我们再来实验一下主线程和单个子线程
public class condition {
public static void main(String[] args) { MyThread myThread = new MyThread();
myThread.setName("子线程");//设定子线程名字
myThread.start();
try {
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println("主线程运行完毕");
}
} class MyThread extends Thread { @Override
public void run(){
for(int i=0;i<5;i++) {
System.out.println(i+"["+this.getName()+"]");
}
}
}
结果为
0[子线程]
1[子线程]
2[子线程]
3[子线程]
4[子线程]
主线程运行完毕
两个或多个子线程之间的顺序同样如此,
如果执行顺序限制为 【子线程1 → 子线程2 → 主线程结束】
public class condition {
public static void main(String[] args) { MyThread t1 = new MyThread("子线程1");
MyThread t2 = new MyThread("子线程2"); try {
t1.start();
t1.join();//join()方法只有在调用start()方法后使用才有意义
t2.start();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程结束");
}
} class MyThread extends Thread { public MyThread(String string) {
this.setName(string);
} @Override
public void run(){
for(int i=0;i<5;i++) {
System.out.println(i+"["+this.getName()+"]");
}
}
}
结果为:
0[子线程1]
1[子线程1]
2[子线程1]
3[子线程1]
4[子线程1]
0[子线程2]
1[子线程2]
2[子线程2]
3[子线程2]
4[子线程2]
主线程结束
参考:https://www.cnblogs.com/songshu120/p/7966314.html(多线程创建的三种方式)
【Java】多线程相关复习—— 线程的创建、名字、运行情况以及顺序控制(join方法) 【一】的更多相关文章
- Java多线程并发01——线程的创建与终止,你会几种方式
本文开始将开始介绍 Java 多线程与并发相关的知识,多谢各位一直以来的关注与支持.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程的创建方式 在 Java 中,用户常用的主动创建 ...
- Java多线程并发02——线程的生命周期与常用方法,你都掌握了吗
在上一章,为大家介绍了线程的一些基础知识,线程的创建与终止.本期将为各位带来线程的生命周期与常用方法.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程生命周期 一个线程不是被创建了 ...
- -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中
本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait( ...
- Java多线程(三)如何创建线程
点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...
- Java多线程相关的
很多小伙伴在学习Java的时候,总是感觉Java多线程在实际的业务中很少使用,以至于不会花太多的时间去学习,技术债不断累积!等到了一定程度的时候对于与Java多线程相关的东西就很难理解,今天需要探讨的 ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- Java多线程系列--“JUC线程池”02之 线程池原理(一)
概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...
- Java多线程系列--“JUC线程池”03之 线程池原理(二)
概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...
- Java多线程系列--“JUC线程池”04之 线程池原理(三)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...
随机推荐
- pat04-树9. Path in a Heap (25)
04-树9. Path in a Heap (25) 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue Insert ...
- QML 程序运行效率
同样的程序,在 Windows 下面启动时非常慢,而在 Linux 上启动时很快,一方面是因为 qml 界面的创建耗时不同,另一方面是因为读取文件的用时相差太大导致. On Linux 在 Linux ...
- HDU 4349——Xiao Ming's Hope——————【Lucas定理】
Xiao Ming's Hope Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- AJAX重点知识的心得体会
下面就为大家带来一篇 AJAX重点知识的心得体会.学习还是有点帮助的,给大家做个参考吧. AJAX是什么? 是Asynchronous Javascript And XML的首字母的缩写, 它不是一门 ...
- [HZOI 2015]复仇的序幕曲
[题目描述] 你还梦不梦痛不痛,回忆这么重你怎么背得动 ----序言 当年的战火硝烟已经渐渐远去,可仇恨却在阿凯蒂王子的心中越来越深 他的叔父三年前谋权篡位,逼宫杀死了他的父王,用铁血手腕平定了国内所 ...
- JavaScript 中 call,apply 和 bind
call and apply 改变函数内部this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数. function test() {} test() == test.ca ...
- JSON FILE NOT FOUND?
(WIN7+IIS7) 搞一个小测试,一个小程序,用一个JSON文件来显示数据, 用HTML 访问是完全没有问题的,可是一放到IIS下,就出现无法访问, CONSOLE:提示 NOT FOUND 原 ...
- canvas剪辑区域
- constrained属性
hibernate文档上是这么写的: constrained(约束) (可选) 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束.这个选项影响save ...
- X-Cart-5.3.1.4 (Ubuntu 16.04)
平台: Ubuntu 类型: 虚拟机镜像 软件包: x-cart-5.3.1.4 commercial ecommerce open-source x-cart 服务优惠价: 按服务商许可协议 云服务 ...