多线程的实现方案有两种
- 继承Thread类
- 实现Runnable接口
相比继承Thread类,实现Runnable接口的好处
- 避免了Java单继承的局限性
- 适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现 了面向对象的设计思想
进程和线程
进程:是正在运行的程序
是系统进行资源分配和调用的独立单位
每一个进程都有它自己的内存空间和系统资源
线程:是进程中的单个顺序控制流,是一条执行路径
单线程:一个进程如果只有一条执行路径,则称为单线程程序
多线程:一个进程如果有多条执行路径,则称为多线程程序
实现多线程方式一:继承Thread类
thread方法:
实现步骤 :
定义一个类MyThread继承Thread类
在MyThread类中重写run()方法
创建MyThread类的对象
启动线程
设置和获取线程名称的方法:
线程优先级
线程调度:
分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一 个,优先级高的线程获取的 CPU 时间片相对多一些
Java使用的是抢占式调度模型
随机性:假如计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也 就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一 定的
优先级相关的方法:
统一代码演示:
自定义线程类:为了方便演示 循环次数设置的少了点
public class MyThread extends Thread{
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
//get 获取线程的名称
String name = getName();
System.out.println(name + ":" +i);
}
}
}
测试类:
public class MyThreadTest {
public static void main(String[] args) {
MyThread m1 = new MyThread();
//也可通过有参构造来给线程命名
MyThread m2 = new MyThread("线程2");
//setName 命名线程的方法
m1.setName("线程1");
m2.setName("线程2");
/*m1.start();
m2.start();*/
//final int getPriority() 返回此线程的优先级
//final void setPriority(int newPriority)
//更改此线程的优先级 线程默认优先级是5;线程优先级的范围 是:1-10
m1.setPriority(10);
System.out.println(m1.getPriority());
System.out.println(m2.getPriority());
//获取线程优先级值
System.out.println(Thread.MIN_PRIORITY);
System.out.println(Thread.MAX_PRIORITY);
System.out.println(Thread.NORM_PRIORITY);
m1.start();
m2.start();
//Thread currentThread() 返回对当前正在执行的线程对象的引用
System.out.println(Thread.currentThread().getName());
}
}
运行结果:
线程控制
相关方法:
sleep演示代码:
public class ThreadSleep extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+ ":" + i);
try {
//让正在执行的线程休息一会,休息结束后继续执行
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadSleepTest {
public static void main(String[] args) {
ThreadSleep ts1 = new ThreadSleep();
ThreadSleep ts2 = new ThreadSleep();
ThreadSleep ts3 = new ThreadSleep();
ts1.setName("曹操");
ts2.setName("孙权");
ts3.setName("刘备");
ts1.start();
ts2.start();
ts3.start();
}
}
控制台结果:打印效果,每0.5秒一次
截取部分:
join代码演示:join表示当前线程执行完后其他线程才开始执行
public class ThreadJoin extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + ":" + i);
}
}
}
public class ThreadJoinTest {
public static void main(String[] args) {
ThreadJoin tj1 = new ThreadJoin();
ThreadJoin tj2 = new ThreadJoin();
ThreadJoin tj3 = new ThreadJoin();
tj1.setName("皇帝");
tj2.setName("大儿子");
tj3.setName("二儿子");
tj1.start();
try {
tj1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
tj2.start();
tj3.start();
}
}
运行结果: 被设置为join的皇帝挂掉之后两个儿子可以争夺皇位
截取部分:
daemon演示代码:运行的线程结束后退出jvm 守护线程被迫停止
public class ThreadDaemon extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + ":" + i);
}
}
}
public class ThreadDaemonTest {
public static void main(String[] args) {
ThreadDaemon td1 = new ThreadDaemon();
ThreadDaemon td2 = new ThreadDaemon();
td1.setName("关羽");
td2.setName("张飞");
//设置主线程为刘备 主线程执行完后如果其他的线程都是守护线程,这时JVM将退出
Thread.currentThread().setName("刘备");
//设置守护线程
td1.setDaemon(true);
td2.setDaemon(true);
td1.start();
td2.start();
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
运行结果: 刘备执行到2的时候 jvm退出,关羽和张飞被迫停止
线程的生命周期
实现多线程方式二:实现Runnable接口
Thread构造方法
实现步骤
定义一个类MyRunnable实现Runnable接口
在MyRunnable类中重写run()方法
创建MyRunnable类的对象
创建Thread类的对象,把MyRunnable对象作为构造方法的参数
启动线程
演示代码:
public class MyRunable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
/**
* Thread(Runnable target) 分配一个新的Thread对象
* Thread(Runnable target, String name) 分配一个新的Thread对象
*/
public class MyRunableTest {
public static void main(String[] args) {
//创建MyRunnaable对象
MyRunable mr = new MyRunable();
Thread t1 = new Thread(mr,"飞机");
Thread t2 = new Thread(mr,"高铁");
t1.start();
t2.start();
}
}
运行结果: