我是靠谱客的博主 苗条未来,这篇文章主要介绍线程(Thread)(代码)继承Thread类线程调度线程控制:实现Runnable接口,现在分享给大家,希望可以做个参考。

在了解线程之前,我们先看看线程与进程的区别

进程:是正在运行的程序

  • 是系统进行资源分配和调用的独立单位
  • 每一个进程都有它自己的内存空间和系统资源

线程:是进程中的单个顺序控制流,是一条执行路径

  • 单线程:一个进行如果只有一条执行路径,则称为单线程程序
  • 多线程:一个进程如果有多条执行路径,则称为多线程程序

比如:

一个微信客户端则是一个进程

如果你和一个妹纸视频,则是单线程

如果你同时传视频文件给多个妹子,则就是多线程

多线程的实现方式有2种:

  • 继承Thread类
  • 实现Runnable接口

继承Thread类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:21 */ public class MyThread1 extends Thread { @Override public void run() { for(int i=0;i<5;i++){ System.out.println(this.getName()+","+i); } } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:20 */ public class ThreadDemo1 { public static void main(String[] args) { MyThread1 my1 = new MyThread1(); MyThread1 my2 = new MyThread1(); my1.run(); my2.run(); } }

输出:

Thread-0,0
Thread-0,1
Thread-0,2
Thread-0,3
Thread-0,4
Thread-1,0
Thread-1,1
Thread-1,2
Thread-1,3
Thread-1,4

发现输出的结果是按顺序来的,并不是多线程,那时因为:

  • run():封装线程执行的代码,直接调用,相当于普通方法的调用
  • start():启动线程,然后有JVM调用此线程的run()方法

所以要调用start方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:21 */ public class MyThread1 extends Thread { public MyThread1() { } public MyThread1(String name) { super(name); } @Override public void run() { for(int i=0;i<100;i++){ System.out.println(this.getName()+","+i); } } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:20 */ public class ThreadDemo1 { public static void main(String[] args) { MyThread1 my1 = new MyThread1("第1个线程"); MyThread1 my2 = new MyThread1("第2个线程"); my1.start(); System.out.println("当前线程名字"+Thread.currentThread().getName()); my2.start(); } }

输出:

当前线程名字main
第2个线程,0
第2个线程,1
第1个线程,0
第1个线程,1
第1个线程,2
第2个线程,2
第2个线程,3
第1个线程,3
第1个线程,4

.....省略

多线程已经执行,并且是随机的,这个和线程调度有关

线程调度

线程有2种调度模型

  • 分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
  • 抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些

Java使用的是抢占式调度模型

假如计算机只有一个CPU,那么CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的。

Thread类中设置和获取线程优先级的方法:

  • public final int getPriority():返回此线程的优先级
  • public final void setPriority(int newPriority):更改此线程的优先级

Java中线程的优先级范围是1-10,默认优先级是5

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:21 */ public class MyThread1 extends Thread { public MyThread1() { } public MyThread1(String name) { super(name); } @Override public void run() { for(int i=0;i<5;i++){ System.out.println(this.getName()+","+i); } } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:20 */ public class ThreadDemo1 { public static void main(String[] args) { MyThread1 my1 = new MyThread1("第1个线程"); MyThread1 my2 = new MyThread1("第2个线程"); System.out.println("线程默认优先级"+Thread.NORM_PRIORITY); System.out.println("线程最小优先级"+Thread.MIN_PRIORITY); System.out.println("线程最大优先级"+Thread.MAX_PRIORITY); my1.setPriority(1); my2.setPriority(10); my1.start(); my2.start(); } }

输出:

线程默认优先级5
线程最小优先级1
线程最大优先级10
第2个线程,0
第1个线程,0
第2个线程,1
第2个线程,2
第2个线程,3
第2个线程,4
第1个线程,1
第1个线程,2
第1个线程,3
第1个线程,4

线程控制:

  • static void sleep(long millis):使当前正在执行的线程停留(暂停执行)指定的毫秒数
  • void join():等待这个线程死亡
  • void setDaemon(boolean on):将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出
复制代码
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
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:21 */ public class MyThread1 extends Thread { public MyThread1() { } public MyThread1(String name) { super(name); } @Override public void run() { for(int i=0;i<5;i++){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.getName()+","+i); } } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:20 */ public class ThreadDemo1 { public static void main(String[] args) throws Exception{ MyThread1 my1 = new MyThread1("第1个线程"); MyThread1 my2 = new MyThread1("第2个线程"); my1.start(); my2.start(); } }

输出:

第1个线程,0
第2个线程,0
第2个线程,1
第1个线程,1
第2个线程,2
第1个线程,2
第2个线程,3
第1个线程,3
第1个线程,4
第2个线程,4 

 结果是必然的,因为我们每执行一次,休眠一秒,这样有足够的时间让下一个线程争取CPU

我们再来看看void join():等待这个线程死亡

复制代码
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
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:21 */ public class MyThread1 extends Thread { public MyThread1() { } public MyThread1(String name) { super(name); } @Override public void run() { for(int i=0;i<5;i++){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.getName()+","+i); } } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:20 */ public class ThreadDemo1 { public static void main(String[] args) throws Exception{ MyThread1 my1 = new MyThread1("第1个线程"); MyThread1 my2 = new MyThread1("第2个线程"); my1.start(); my1.join(); my2.start(); } }

输出:

第1个线程,0
第1个线程,1
第1个线程,2
第1个线程,3
第1个线程,4
第2个线程,0
第2个线程,1
第2个线程,2
第2个线程,3
第2个线程,4

即使我们每执行一次,休眠一秒,这样有足够的时间让下一个线程争取CPU,但是我们调用了my1.join();也就是要等my1线程死亡了,my2才调用。

接着看void setDaemon(boolean on):将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出。

我们把代码调整下,让MyThread1重写的run()方法循环500次,然后其实例都设置为守护线程

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:21 */ public class MyThread1 extends Thread { public MyThread1() { } public MyThread1(String name) { super(name); } @Override public void run() { for(int i=0;i<500;i++){ System.out.println(this.getName()+","+i); } } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:20 */ public class ThreadDemo1 { public static void main(String[] args) { MyThread1 my1 = new MyThread1("第1个线程"); MyThread1 my2 = new MyThread1("第2个线程"); Thread.currentThread().setName("主线程"); my1.setDaemon(true); my2.setDaemon(true); my1.start(); my2.start(); for(int i =0;i<10;i++){ System.out.println(Thread.currentThread().getName()+","+i); } } }

输出:

主线程,0
主线程,1
主线程,2
主线程,3
主线程,4
第2个线程,0
第1个线程,0
第1个线程,1
第1个线程,2
第1个线程,3
第1个线程,4
第2个线程,1
主线程,5
主线程,6
主线程,7
主线程,8
主线程,9
第2个线程,2
第2个线程,3
第2个线程,4
第2个线程,5

从结果可以看出,当主线程执行完后,守护线程会挂掉,但是并不是立即挂掉,而是很快就挂掉。

实现Runnable接口

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:21 */ public class MyThread2 implements Runnable { public MyThread2() { } @Override public void run() { for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+","+i); } } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.Thread; /** * @author 林高禄 * @create 2020-05-14-10:20 */ public class ThreadDemo2 { public static void main(String[] args) { MyThread2 my1 = new MyThread2(); Thread t1 = new Thread(my1,"第1个线程"); Thread t2 = new Thread(my1,"第2个线程"); t1.start(); t2.start(); } }

实现Runnable接口,其调用方式也不一样

  • Thread(Runnable target)
  • Thread(Runnable target, String name)

 

最后

以上就是苗条未来最近收集整理的关于线程(Thread)(代码)继承Thread类线程调度线程控制:实现Runnable接口的全部内容,更多相关线程(Thread)(代码)继承Thread类线程调度线程控制内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(74)

评论列表共有 0 条评论

立即
投稿
返回
顶部