【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之 基 ...
随机推荐
- zuul路由网关
zuul作为网关组件,主要用来管理api请求接口(统一对外暴露,负载均衡),身份认证,流量监控等.它是通过servlet来实现的,核心是一系列过滤器,可以在请求的发起跟相应返回阶段进行一系列的处理. ...
- 本机访问其它电脑上的oracle数据库
最近发现很多人问到怎么才能访问别人机子上的oracle,这里来给大家做个示范 借助工具的话,oracle就自己带了两个配置和移值助手下面:net configuration assistant 和ne ...
- Asp.Net Mvc: 应用BindAttribute
环境: Windows 2008, VS 2008 SP1, Asp.Net Mvc RC1 ----------------------------------------------------- ...
- C#注册URL协议,使用浏览器打开本地程序,类似网页上点了QQ交谈打开本地QQ客户端程序
本教程适用于Windows系统 从浏览器上打开本地程序,主要用到了本地URL协议,其实主要就是改注册表 先建立一个项目,我建的是控制台项目 在Program.cs写2个静态方法用来添加注册表.移除注册 ...
- 零度4W1H提问规则
WHAT:您现在的需求和目的是什么,请按条理描述清楚. WHERE:在什么平台.环境和工具下发生此问题. WHEN:何时发生的该问题,该问题是否能够重现. WHY:为什么不能通过搜索引擎来解决您的问题 ...
- DataColumn.Expression提示“...循环引用”的错误
我碰到这个问题的时候,在网上找了找,找到了有好几个提出这个问题的人,但是都没有得到解答,当时很郁闷.然后再看看msdn中的解释与自己的测试,才把这个问题给解决了. 代码如下: person.Colum ...
- JavaScript流程控制语句脑图
JavaScript流程控制语句脑图 图片是从网上找来的,在这记录一下,以备后面需要的时候查找方便. JavaScript通过规定的语句让有条件的按照一定的方式执行. 分为:循环语句 while do ...
- CSS3制作3D旋转视频展示区
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- mysql的三种索引
MySQL中的索引分为3种: 1,主键索引:即用主键当唯一索引 2,常规索引:实现方式为B树和哈希表 3,全文索引:实现原理类似倒排索引,常用来查询字段中包含关键字 下面复习下B-TREE和hash- ...
- tomcat启动部署APP报错:This is very likely to create a memory leak
This is very likely to create a memory leak的错误,网上很多,原因也是各种各样,这里也仅提供一个解决的思路. 问题描述:启动tomcat时,不能访问部署的AP ...