同时执行多个任务,例如一个人一边听歌,一边跳舞
定义一个MyThread类继承Thread类,重写里面的run方法
package com.itxs.demo01;
/**
* @Classname : MyThread
* @Description : TODO 自定义线程继承Thread类
* @Author : [email protected]
*/
public class MyThread extends Thread{
@Override
public void run() {
//super.run();
for (int i = 0; i < 20; i++) {
System.out.println("i = " + i);
}
}
}
测试多线程类
package com.itxs.demo01;
/**
* @Classname : demo01
* @Description : TODO 多线程的测试类
* @Author : [email protected]
*/
public class demo01 {
public static void main(String[] args) {
// 线程对象创建
MyThread my01 = new MyThread();
MyThread my02 = new MyThread();
MyThread my03 = new MyThread();
MyThread my04 = new MyThread();
//开启线程的方法start
my01.start();
my02.start();
my03.start();
my04.start();
}
}
自定义线程继承Thread类
package com.itxs.demo02;
/**
* @Classname : MyThread
* @Description : TODO 自定义线程 - 继承Thread类
* @Author : [email protected]
*/
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
// this.getName获取类中自己的Name值
System.out.println(this.getName() + " i =" + i);
}
}
}
测试线程
package com.itxs.demo02;
/**
* @Classname : demo01
* @Description : TODO 多线程名字设置的方式
* @Author : [email protected]
*/
public class demo01 {
public static void main(String[] args) {
//创建线程对象
// 方式一:通过构造方法进行设置每个线程名字
MyThread my01 = new MyThread("线程01");
MyThread my02 = new MyThread("线程02");
MyThread my03 = new MyThread("线程03");
MyThread my04 = new MyThread();
// 方式二:通过方法setName设置线程名字
// my01.setName("线程01");
// my02.setName("线程02");
// my03.setName("线程03");
my04.setName("线程04");
//开启线程
my01.start();
my02.start();
my03.start();
my04.start();
}
}
获取正在运行的线程
Thread.currentThread()
通过上面的方法,获取到每个运行线程的名字
package com.itxs.demo02;
/**
* @Classname : MyThread
* @Description : TODO 自定义线程(输出0-19) - 继承Thread类
* @Author : [email protected]
*/
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
// this.getName获取类中自己的Name值
System.out.println(Thread.currentThread().getName() + " i =" + i);
}
}
}
package com.itxs.demo02;
/**
* @Classname : demo03
* @Description : TODO 获取每个正在运行的线程的方法
* @Author : [email protected]
*/
public class demo03 {
public static void main(String[] args) {
// 创建几个线程对象,设置每个线程的名字
MyThread my01 = new MyThread("多线程01");
MyThread my02 = new MyThread("多线程02");
MyThread my03 = new MyThread("多线程03");
MyThread my04 = new MyThread("多线程04");
//开启线程
my01.start();
my02.start();
my03.start();
my04.start();
// main 其实也是一个线程,但是却是主线程
// 输出0-19
//设置主线程名字的方法 Thread.currentThread是获取正在运行的线程
//setName是设置名字
Thread.currentThread().setName("主线程");
for (int i = 0; i < 20; i++) {
System.out.println( Thread.currentThread().getName()+"i = " + i);
}
}
}
两种线程调度模型
分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间
抢占调度模型:优先让优先级高的线程使用 CPU,如果线程的欧优先级相同,那么随机选择一个,优先级高的线程获取的 CPU 占用时间会相对多一丢丢丢丢丢……
Java 使用的是抢占式的调度模型
Thread 类中设置和获取线程优先级的方法
public final int getPriority()
:返回次线程的优先级
public final void setProiority(int newPriority)
:更改次线程的优先级
自定义的线程类-继承Thread类
package com.itxs.demo02;
/**
* @Classname : MyThread
* @Description : TODO 自定义线程(输出0-19) - 继承Thread类
* @Author : [email protected]
*/
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
// this.getName获取类中自己的Name值
System.out.println(Thread.currentThread().getName() + " i =" + i);
}
}
}
优先级测试
package com.itxs.demo02;
/**
* @Classname : demo02
* @Description : TODO 线程调度测试
* @Author : [email protected]
*/
public class demo02 {
public static void main(String[] args) {
// 创建线程对象
MyThread mt01 = new MyThread("线程01");
MyThread mt02 = new MyThread("线程02");
MyThread mt03 = new MyThread("线程03");
//修改线程的优先级
mt01.setPriority(Thread.MIN_PRIORITY);//1
mt02.setPriority(Thread.NORM_PRIORITY);//5
mt03.setPriority(Thread.MAX_PRIORITY);//10
// 线程的优先级输出
// System.out.println(mt01.getPriority());
// System.out.println(mt02.getPriority());
// System.out.println(mt03.getPriority());
//开启线程测试那个线程优先完成
mt03.start();
mt02.start();
mt01.start();
}
}
方法名 | 说明 |
---|---|
static void sleep(long ms) |
使当前正在执行的线程停留指定的毫秒数 |
void join() |
等待这个进程死亡 |
void setDaemon(boolean on) |
将此线程标记为守护进程,当运行线程都是守护线程时,JVM 将退出 |
案例:华山论剑
自定义线程类
package com.itxs.demo02;
/**
* @Classname : MyThread
* @Description : TODO 自定义一个线程 - 继承Thread类
* @Author : [email protected]
*/
public class MyThread extends Thread{
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 1; i <=20 ; i++) {
System.out.println(Thread.currentThread().getName() + "出了第"+i+"招");
try {
Thread.sleep(1000);//停留一秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
sleep测试类
package com.itxs.demo02;
/**
* @Classname : demo02
* @Description : TODO 线程测试 - sleep
* @Author : [email protected]
*/
public class demo02 {
public static void main(String[] args) {
//创建线程对象
MyThread mt01 = new MyThread("黄固");
MyThread mt02 = new MyThread("欧阳锋");
MyThread mt03 = new MyThread("段智兴");
MyThread mt04 = new MyThread("洪七公");
//开启线程
mt01.start();
mt02.start();
mt03.start();
mt04.start();
}
}
歌曲《天下》,原唱:张杰,翻唱:池瑶和高鱼
package com.itxs.demo03;
/**
* @Classname : MyThread
* @Description : TODO
* @Author : [email protected]
*/
public class MyThread extends Thread {
public MyThread() {
super();
}
public MyThread(String name) {
super(name);
}
// 定义一个数组存放歌词
String[] song = {"烽烟起寻爱似浪淘沙",
"遇见她如春水映梨花",
"挥剑断天涯",
"相思轻放下"
};
@Override
public void run() {
for (int i = 0; i < song.length; i++) {
System.out.println(Thread.currentThread().getName() + "正在唱:" + song[i]);
}
}
}
测试-张杰唱完后,两个翻唱继续唱
package com.itxs.demo03;
/**
* @Classname : demo01
* @Description : TODO
* @Author : [email protected]
*/
public class demo01 {
public static void main(String[] args) throws InterruptedException {
//创建线程
MyThread mt01 = new MyThread("张杰");
MyThread mt02 = new MyThread("池瑶");
MyThread mt03 = new MyThread("高鱼");
//开启线程
mt01.start();
mt01.join();//等待张杰唱完,mt01执行完后执行后面的线程
mt02.start();
mt03.start();
}
}
守护线程,总结就是当创建的线程对象设置为守护线程后,主线程里面的内容执行完后,所有开启的多线程都会停止执行
自定义的线程,执行20次循环
package com.itxs.demo04;
/**
* @Classname : MyThread
* @Description : TODO - 自定义线程
* @Author : [email protected]
*/
public class MyThread extends Thread{
public MyThread() {
super();
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+"报数:"+i);
}
}
}
测试守护线程
package com.itxs.demo04;
/**
* @Classname : demo01
* @Description : TODO
* @Author : [email protected]
*/
public class demo01 {
public static void main(String[] args) {
//创建线程对象
MyThread mt01 = new MyThread("1号");
MyThread mt02 = new MyThread("2号");
MyThread mt03 = new MyThread("3号");
System.out.println("开始报数");
//mt01,02,03设置为守护线程
mt01.setDaemon(true);
mt02.setDaemon(true);
mt03.setDaemon(true);
// 线程开启
mt01.start();
mt02.start();
mt03.start();
// 主线程执行三次循环
for (int i = 0; i < 3; i++) {
System.out.println("报数中");
}
System.out.println("停止报数");
}
}
新建:创建线程对象(通过 start()
进入下一个环节)
就绪:有执行资格,没有执行权(抢占 CPU 的执行权)
运行:有执行资格,有执行权(可能被其他线程抢走 CPU 的执行权,则回到就绪状态,若遇到阻塞式方法,则失去运行权和执行这个,等待,当阻塞方法调用结束之后,回到就绪状态)
死亡:线程死亡,成为垃圾