概述
在了解线程之前,我们先看看线程与进程的区别
进程:是正在运行的程序
- 是系统进行资源分配和调用的独立单位
- 每一个进程都有它自己的内存空间和系统资源
线程:是进程中的单个顺序控制流,是一条执行路径
- 单线程:一个进行如果只有一条执行路径,则称为单线程程序
- 多线程:一个进程如果有多条执行路径,则称为多线程程序
比如:
一个微信客户端则是一个进程
如果你和一个妹纸视频,则是单线程
如果你同时传视频文件给多个妹子,则就是多线程
多线程的实现方式有2种:
- 继承Thread类
- 实现Runnable接口
继承Thread类
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);
}
}
}
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方法
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);
}
}
}
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
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);
}
}
}
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虚拟机将退出
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);
}
}
}
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():等待这个线程死亡
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);
}
}
}
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次,然后其实例都设置为守护线程
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);
}
}
}
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接口
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);
}
}
}
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类线程调度线程控制:实现Runnable接口所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复