java多线程入门
接下来,我们讲一讲主线程、线程组、线程优先级、精灵线程/守护线程
在讲之前,我们先简要的说一说,什么是线程,进程,程序
等一下,我们直接po代码和截图,直接看具体的案例
多线程即在同一时间,可以做多件事情(说白了,就是齐头并进)
单线程就是按部就班
程序:一系列命令/指令的集合,说白了,就是一堆英文字母和数字组成的指令,这堆英文字母和数字需要符合编程语言的语法规则!(程序是静态的,也就是说,程序员编写好了一个程序,那个程序就静静的、安静的躺在电脑磁盘上,那就是程序)
进程:可以理解成动态的程序,说白了,就是把安静的躺在电脑磁盘上的程序打开运行,程序一打开运行,就会在电脑的内存中运行,占用电脑内存资源,占用cpu资源,这就是一个进程,简而言之,就是已经在内存中运行的程序就是进程
线程:线程就是进程/程序中的相对独立的代码段,比进程更小的运行单位,多个线程构成一个进程,线程是依附于进程的。
进程是由操作系统来调度的!
线程是由进程来调度的,线程是依附于进程的!
创建多线程有2种方式,分别是继承线程Thread类,实现Runnable接口
注意:
1.继承Thread类的线程类不能再继承其他类了(因为在Java中,一个类不能同时继承多个类,java是单继承的)
2.我们在java中创建线程,建议使用实现Runnable接口的方式,好处就是避免了单继承的局限性。比如当一个student类继承了person类,再需继承其他的类时就不能了,所以在定义线程时,建议使用实现Runnable接口的方式,因为对系统的侵入性比较小!(在java中,一个类可以实现多个接口)
接下来,直接po代码和截图
案例不算太难,代码量也不多,希望大家耐心看完,以张无忌、赵敏、周芷若为案例
Zhangwuji类
package com.demo.thread;
/**
* 张无忌类
*/
public class Zhangwuji {
public void zhui() {
for (int i = 0; i < 5; i++) {
System.out.println("张无忌追啊追----");
}
}
}
Zhangwuji2类
package com.demo.thread;
/**
* 方式1,继承Thread类,这种方式对系统的侵入性更大,如
* 果本类下面还有子类,那么就等于本类的子类也继承了Thread类的多线程机制,所
* 以继承Thread类这种方式对系统的侵入性更大
* (在java中,是单继承的,但是java中的一个类可以实现多个接口)
* 本类继承Thread类后,就不能再继承其他类了,所以,继承Thread类这种方式,扩展性不太好,所
* 以建议使用实现Runnable接口这种方式
* 张无忌类
*/
public class Zhangwuji2 extends Thread{
//线程体
@Override
public void run() {
zhui();
}
public void zhui() {
for (int i = 0; i < 5; i++) {
System.out.println("张无忌追啊追----");
}
}
}
Zhangwuji3类
package com.demo.thread;
/**
* 方式2,实现Runnable接口,这种方式对系统的侵入性更小,而且本
* 类还可以实现其他的接口和继承其他的类,扩展性更好(在java中,是单继承的,但
* 是java中的一个类可以实现多个接口)
* 张无忌类
*/
public class Zhangwuji3 implements Runnable{
//线程体
@Override
public void run() {
zhui();
}
public void zhui() {
for (int i = 0; i < 5; i++) {
System.out.println("张无忌追啊追----");
}
}
}
Zhangwuji4类
package com.demo.thread;
/**
* 方式2,实现Runnable接口,这种方式对系统的侵入性更小,而且本
* 类还可以实现其他的接口和继承其他的类,扩展性更好(在java中,是单继承的,但
* 是java中的一个类可以实现多个接口)
* 张无忌类
*/
public class Zhangwuji4 implements Runnable{
//线程体
@Override
public void run() {
zhui();
}
public void zhui() {
for (int i = 0; i < 5; i++) {
System.out.println("我是张无忌,我追啊追!!!!!!!!");
}
}
}
Zhaomin类
package com.demo.thread;
/**
* 赵敏类
*/
public class Zhaomin {
public void quan() {
for (int i = 0; i < 5; i++) {
System.out.println("赵敏劝啊劝!!!!");
}
}
}
Zhaomin2类
package com.demo.thread;
/**
* 赵敏类
*/
public class Zhaomin2 extends Thread{
//线程体
@Override
public void run() {
quan();
}
public void quan() {
for (int i = 0; i < 5; i++) {
System.out.println("赵敏劝啊劝!!!!");
}
}
}
Zhouzhiruo类
package com.demo.thread;
/**
* 周芷若类
*/
public class Zhouzhiruo {
public void pao() {
for (int i = 0; i < 5; i++) {
System.out.println("周芷若生气气了,跑啊跑....");
}
}
}
Zhouzhiruo2类
package com.demo.thread;
/**
* 周芷若类
*/
public class Zhouzhiruo2 extends Thread{
//线程体
@Override
public void run() {
pao();
}
public void pao() {
for (int i = 0; i < 5; i++) {
System.out.println("周芷若生气气了,跑啊跑....");
}
}
}
UsualThread类
这是一个普通的用户线程,UsualThread类(ps:我们可以把守护线程以外的线程,都可以叫做是用户线程)
package com.demo.thread;
//这是一个普通的用户线程
public class UsualThread extends Thread {
@Override
public void run() {
int a = 0;
while (true) {
System.out.println("我是一个普通的用户线程" + a++);
}
}
}
WaterSupplyThread类
周芷若和张无忌和赵敏,他们肯定也会口渴,肯定是要喝水的,我这里写了一个供水线程
供水线程,WaterSupplyThread类
package com.demo.thread;
//这是一个供水线程(是一个精灵线程,精灵线程又叫做守护线程)
public class WaterSupplyThread extends Thread {
@Override
public void run() {
int i = 0;
while (true) {
System.out.println("我是一个供水的守护线程" + i++);
}
}
}
Test类
package com.demo.thread;
public class Test {
/**
* 没使用线程
*/
public static void main(String[] args) {
//如下这种方式就是单线程的方式(单线程就是我们所说的按部就班)
Zhouzhiruo zhouzhiruo = new Zhouzhiruo();
Zhangwuji zhangwuji = new Zhangwuji();
Zhaomin zhaomin = new Zhaomin();
zhouzhiruo.pao();
zhangwuji.zhui();
zhaomin.quan();
}
}
运行结果:
Test2类
package com.demo.thread;
public class Test2 {
/**
* 使用了线程
*/
public static void main(String[] args) {
//如下这种方式就是多线程的方式(多线程就是我们所说的齐头并进)
Zhouzhiruo2 zhouzhiruo2 = new Zhouzhiruo2();
Zhangwuji2 zhangwuji2 = new Zhangwuji2();
Zhaomin2 zhaomin2 = new Zhaomin2();
zhouzhiruo2.start();
zhangwuji2.start();
zhaomin2.start();
}
}
运行结果:可以多执行几次,每次运行的结果可能不一样
Test3类
package com.demo.thread;
public class Test3 {
/**
* 使用了线程
*/
public static void main(String[] args) {
//如下这种方式就是多线程的方式(多线程就是我们所说的齐头并进)
Zhouzhiruo2 zhouzhiruo2 = new Zhouzhiruo2();
Zhangwuji3 zhangwuji3 = new Zhangwuji3();
Zhaomin2 zhaomin2 = new Zhaomin2();
//构造方法传参
Thread cpu = new Thread(zhangwuji3);
zhouzhiruo2.start();
cpu.start();
zhaomin2.start();
}
}
运行结果:可以多执行几次,每次运行的结果可能不一样
接下来,讲主线程和线程优先级
主线程和线程优先级
TestMainThread类
package com.demo.thread;
public class TestMainThread {
public static void main(String[] args) {
/**
* 在java程序启动时,有一个线程立即执行,我们把该线程称为程序的主线程
* 主线程的重要性体现在两方面
* 1.它是产生其他子线程的线程
* 2.通常它必须最后完成执行,因为它执行各种关闭动作
*
*/
//当前正在运行的线程对象
//主线程
Thread currentThread = Thread.currentThread();//Thread类的静态方法
System.out.println(currentThread + "当前线程的名称=" +currentThread.getName());
//我们可以给线程设置名称
currentThread.setName("jiangxi");
System.out.println(currentThread + "当前线程的名称=" +currentThread.getName());
//如下这种方式就是多线程的方式(多线程就是我们所说的齐头并进),线程有优先级的概念,线程的优先级默认为5
Zhouzhiruo2 zhouzhiruo2 = new Zhouzhiruo2();
Zhangwuji3 zhangwuji3 = new Zhangwuji3();
Zhaomin2 zhaomin2 = new Zhaomin2();
//构造方法传参
Thread cpu = new Thread(zhangwuji3);//构造器传参
System.out.println("线程名字=" + cpu.getName() + "******");
System.out.println("线程信息=" + cpu.currentThread().getName() + "-----");
System.out.println("线程信息=" + cpu.currentThread() + "######");
// 构造函数传参
// cpu = new Thread(new Zhangwuji4());// 构造器传参
// System.out.println("线程名字=" + cpu.getName() + "******");
// System.out.println("线程信息=" + cpu.currentThread().getName() + "-----");
// System.out.println("线程信息=" + cpu.currentThread() + "######");
/*
* 注意:
* java线程的优先级并不代表一定会执行,只是说明执行的概率高一些,所以在java中用优
* 先级控制执行顺序是不确定的
*/
//设置优先级,优先级设置成10,优先级最高,属于抢占式策略。(而优先级相同的线程,采用时间片式策略)
//要在调用start()方法前设置优先级,优先级越高,就能获得更多的cpu资源
zhaomin2.setPriority(Thread.MAX_PRIORITY);
System.out.println("赵敏的优先级=" + zhaomin2.getPriority());
//线程的优先级默认为5
System.out.println("周芷若的优先级=" + zhouzhiruo2.getPriority());
//调用start()方法启动线程
zhouzhiruo2.start();
cpu.start();
zhaomin2.start();
//垃圾回收车是一个守护线程(守护线程又叫做精灵线程),垃圾回收车线程的优先级最低,为1级
System.gc();//该行代码的意思是,建议垃圾回收车线程去运行,但是到底会不会运行,这是不一定的
String activeCount = "当前线程组里面,正在活动的线程的数目=";
//当前线程组里面,正在活动的线程的数目
//Thread类的静态方法
System.out.println(activeCount + Thread.activeCount());
}
}
运行结果:可以多执行几次,每次运行的结果可能不一样
接下来,讲线程组
线程组
TestThreadGroup类
package com.demo.thread;
public class TestThreadGroup {
public static void main(String[] args) {
//创建一个线程组,它默认隶属于系统线程组
ThreadGroup jerryThreadGroup = new ThreadGroup("jerryThreadGroup");
System.out.println("####################线程组名字=" + jerryThreadGroup.getName());
System.out.println("###########当前线程组的父线程组名字=" + jerryThreadGroup.getParent().getName());
Zhouzhiruo2 zhouzhiruo2 = new Zhouzhiruo2();
Zhangwuji3 zhangwuji3 = new Zhangwuji3();
Zhaomin2 zhaomin2 = new Zhaomin2();
//构造方法传参
Thread cpu = new Thread(jerryThreadGroup, zhangwuji3);//构造器传参
//调用start()方法启动线程
zhouzhiruo2.start();
cpu.start();
zhaomin2.start();
String activeCount = " 当前线程组里面,正在活动的线程和线程组的数目=";
//当前线程组里面,正在活动的线程的数目
System.out.println("线程组名字=" + jerryThreadGroup.getName() + activeCount + jerryThreadGroup.activeCount());
//通过getThreadGroup()函数得到当前线程隶属的线程组
ThreadGroup threadGroup = zhouzhiruo2.getThreadGroup();
//线程组的activeCount()函数得到当前线程组中活动的线程和线程组数目
System.out.println("线程组名字=" + threadGroup.getName() + activeCount + threadGroup.activeCount());
}
}
运行结果:可以多执行几次,每次运行的结果可能不一样
运行结果,情况1
运行结果,情况2
接下来,讲守护线程(守护线程又叫做精灵线程)
守护线程/精灵线程
TestDaemonThread类
我们可以把守护线程以外的线程,都可以叫做是用户线程
把供水线程设置为守护线程(只要没有用户线程在运行了,那守护线程就会停止,也不会再继续运行了)
package com.demo.thread;
// 测试守护线程(守护线程又叫精灵线程)
public class TestDaemonThread {
public static void main(String[] args) {
Zhouzhiruo2 zhouzhiruo2 = new Zhouzhiruo2();
Zhangwuji3 zhangwuji3 = new Zhangwuji3();
Zhaomin2 zhaomin2 = new Zhaomin2();
// 构造方法传参
Thread cpu = new Thread(zhangwuji3);
WaterSupplyThread waterSupplyThread = new WaterSupplyThread();
//垃圾回收车是一个守护线程(守护线程又叫做精灵线程),垃圾回收车线程的优先级最低,为1级
//把供水线程设置为守护线程(只要没有用户线程在运行了,那守护线程就会停止,也不会再继续运行了)
waterSupplyThread.setDaemon(true);
waterSupplyThread.start();
zhouzhiruo2.start();
cpu.start();
zhaomin2.start();
}
}
运行结果:
只要没有用户线程在运行了,那守护线程就会停止,也不会再继续运行了
TestDaemonThread2类
把供水线程设置为守护线程(只要还有用户线程在运行,那守护线程就不会停止,也在继续运行)
package com.demo.thread;
// 测试守护线程(守护线程又叫精灵线程)
public class TestDaemonThread2 {
public static void main(String[] args) {
Zhouzhiruo2 zhouzhiruo2 = new Zhouzhiruo2();
Zhangwuji3 zhangwuji3 = new Zhangwuji3();
Zhaomin2 zhaomin2 = new Zhaomin2();
UsualThread usualThread = new UsualThread();
// 构造方法传参
Thread cpu = new Thread(zhangwuji3);
WaterSupplyThread waterSupplyThread = new WaterSupplyThread();
//垃圾回收车是一个守护线程(守护线程又叫做精灵线程),垃圾回收车线程的优先级最低,为1级
//把供水线程设置为守护线程(只要还有用户线程在运行,那守护线程就不会停止,也在继续运行)
waterSupplyThread.setDaemon(true);
waterSupplyThread.start();
zhouzhiruo2.start();
cpu.start();
zhaomin2.start();
usualThread.start();
}
}
运行结果: