【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之 基 ...
随机推荐
- 30段有用的javascript代码
1. 如何区分IE及非IE浏览器 if(!+[1,]){ console.log("这是IE浏览器"): } else{ console.log("这不是IE浏览器&qu ...
- c#-day03学习笔记
循环语句 一共有三种 1: For循环 2: while 循环 3: do while 循环 //1 //2 //4 For循环 语法 f ...
- 模糊查询(like)
1. 找出名中包含 “厂”的所有供应商的名select * from provider where pro_name like '%厂%'2.第二个字为华select * from provider ...
- 结合IL和Windbg来看.Net调用继承虚方法的执行顺序
先上测试代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...
- Redis数据类型(字符串)
Redis存放的字符串为二进制是安全的.字符串长度支持到512M. incr 递增数字INCR key 当存储的字符串是整数时,redis提供了一个实用的命令INCR,其作用是让当前键值递增,并返回递 ...
- CSS的框模型(div)与边距(margin、padding)
所谓框模型,例如div标签,你就可以直接把它理解成一个相框. 这个相框里面的相片有高度和宽度,框本身也有一定的宽度.相框和别的相框之间,还有一定的边距. div设置常见属性 border:边框 pad ...
- MarkDown 编辑器学习
MarkDown 编辑器学习 是一种简单快键的文字排版工具,可以用于编写说明文档,鉴于其语法简洁明了,且其渲染生成的样式简单美观,很多开发者也用它来写博客,已被国内外很多流行博客平台所支持.生成的文件 ...
- 栅格那点儿事(四A)---栅格的显示与渲染
栅格的显示与渲染 通过前两章的学习,应该对栅格这个东西不那么陌生了.在这一个部分,我们来看看如何展示出栅格数据最美丽的地方,在ArcGIS中栅格的显示与渲染.在进入细节之前,先来看看在ArcGIS中都 ...
- Excel 解析 (大文件读取)BingExcel
最近在整理一个excel读取与写出的orm框架.使用的saxreader方式,支持百万级别的excel读取. 并且在通常使用中提供了监听的读取方式.如感兴趣的朋友可以稍微了解下 ,项目地址https: ...
- Android getRunningTasks和getRunningAppProcesses失效
Android 5.0以上的getRunningTasks失效,该方法可以获得在前台运行的系统进程.可以用getRunningAppProcesses方法暂时替代. android6.0以上的getR ...