一、创建线程的三种方式

· 继承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方法) 【一】的更多相关文章

  1. Java多线程并发01——线程的创建与终止,你会几种方式

    本文开始将开始介绍 Java 多线程与并发相关的知识,多谢各位一直以来的关注与支持.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程的创建方式 在 Java 中,用户常用的主动创建 ...

  2. Java多线程并发02——线程的生命周期与常用方法,你都掌握了吗

    在上一章,为大家介绍了线程的一些基础知识,线程的创建与终止.本期将为各位带来线程的生命周期与常用方法.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程生命周期 一个线程不是被创建了 ...

  3. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

  4. Java多线程(三)如何创建线程

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  5. Java多线程相关的

    很多小伙伴在学习Java的时候,总是感觉Java多线程在实际的业务中很少使用,以至于不会花太多的时间去学习,技术债不断累积!等到了一定程度的时候对于与Java多线程相关的东西就很难理解,今天需要探讨的 ...

  6. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  7. Java多线程系列--“JUC线程池”02之 线程池原理(一)

    概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...

  8. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  9. Java多线程系列--“JUC线程池”04之 线程池原理(三)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...

随机推荐

  1. IOS Intro - NSDictionary and NSMutableDictionary

    NSDictionary.NSMutableDictionary的基本用法 1.不可变词典NSDictionary 字典初始化 NSNumber *numObj = [NSNumber numberW ...

  2. `aclocal-1.10' is missing on your system

    root@ubuntu31:~/linux-ftools-master# makecd . && /bin/bash /root/linux-ftools-master/missing ...

  3. CSS选择器笔记,element element和element > element 的区别

    看官方解释 element element  例子: div p 官方解释:div内部所有的p元素 就是说 只要p在div内部.如果 p在span内部,span在div内部,p也算在div内部 < ...

  4. pat04-树5. File Transfer (25)

    04-树5. File Transfer (25) 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue We have ...

  5. 快速学习 Python 数据分析包 之 pandas

    最近在看时间序列分析的一些东西,中间普遍用到一个叫pandas的包,因此单独拿出时间来进行学习. 参见 pandas 官方文档 http://pandas.pydata.org/pandas-docs ...

  6. linux 下库的深入调研

    linux操作系统中,linux库文件路径还是比较常用的,于是我研究了一下linux库文件路径,在这里拿出来和大家分享一下,希望对大家有用. 库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程 ...

  7. AngularJS directive 动态 template

    app.directive('testwindow', function() { return { restrict : 'E', template: '<ng-include src=&quo ...

  8. 读取和写入Cookies

    #region 读取或写入cookie 2 /// <summary> 3 /// 写cookie值 4 /// </summary> 5 /// <param name ...

  9. checkBox 全选、全不选、反选

    checkBox的使用: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http: ...

  10. array_map()关于回调函数的总结

    array_map()函数的第一个参数可以是匿名函数,系统函数,也可以是自己自定义的函!在全局空间下,这些函数的调用都很简单 在这里就不多说了!我们主要讨论的是该函数调用类中的方法和静态方法的区别 摘 ...