代码只供学习使用,实际开发中建议遵守Java开发规范,合理分包,不要忽视面向对象方法的重要原则:封装
代码所涉及知识点:
什么是线程、Thread方法和Runnable接口的介绍及创建线程、线程的状态和生命周期、sleep方法和join方法的使用、线程的优先级、线程同步、线程间通信(见另一篇文章,点击访问,Java多线程之——线程间通信实例)
package practice;
/**
*
* @author slvayf
*
*/
// 通过继承Thread类的方式,可以完成多线程的建立,多线程由系统调度交叉执行
class MyThread extends Thread {
// 父类引用,传参修改线程名称
public MyThread(String name) {
super(name);
}
public void run() {
for (int i = 1; i < 6; i++) {
// sleep方法:
// 通过sleep方法使线程休眠(暂停线程的执行1毫秒)
// 但是暂停1毫秒后,线程并不会马上进入执行状态,而是进入可执行状态(Runnable)
// 执行thread类的sleep方法,多次运行程序我们可以发现:
// ___“通过Runnable接口创建的线程”因为不休眠而“通过thread方法创建的线程:线程0、1、2”1毫秒休眠一次
// 所以“通过Runnable接口创建的线程”获得CPU使用权开始执行的概率会更大
// 不过,因为“通过thread方法创建的线程:线程0”执行时虽然1毫秒休眠一次,但因为使用join方法,它是优先执行的
// “通过Runnable接口创建的线程”也可以使用thread类的sleep方法实现类似效果,join相同
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// 休眠中断异常
e.printStackTrace();
}
System.out.println(getName() + "正在执行第" + i + "次");
}
}
}
// 但是继承Thread类这种方式有一个局限性,如果一个类已经有了自己的父类,就不可以继承Thread类,因为java规定类是单继承的
// 如果该类中的还有部分代码需要被多个线程同时执行,只有对该类进行额外的功能扩展,java就提供了一个接口Runnable
// Runnable接口中定义了run方法,其实run方法的定义就是为了存储多线程要运行的代码
// 所以,通常创建线程都用第二种方式,因为,实现Runnable接口可以避免单继承的局限性
// 而且,继承Thread,是可以对Thread类中的方法进行子类复写的
// 但是不需要做这个复写动作,只为定义线程代码存放位置的话,实现Runnable接口更方便一些
// 所以,Runnable接口将线程要执行的任务封装成了对象
// 其实,将多线程要运行的代码的位置单独定义到接口中,为其他类进行功能扩展提供了前提
// 所以,Thread类在描述线程时,内部定义的run方法,也来自于Runnable接口
class PrintRunnable implements Runnable {
@Override
public void run() {
for (int i = 1; i < 6; i++) {
System.out.println(Thread.currentThread().getName() + "正在执行第" + i + "次"+ " 优先级:" + Thread.currentThread().getPriority());
// 主线程和新创建线程默认优先级为5
// 设置t2的优先级为10,多次执行下来我们可以发现,在大多数情况下,t2是要比t1优先执行的,优先级先10后5
// 但有时候t1("通过Runnable接口创建的线程:线程1")还是在t2之前执行
// 其原因是,操作系统确定程序执行优先级,并不是只根据用户设置的优先级,还要综合计算机内存及其它资源利用状况,做出综合判断
// 比如先启动的低优先级的程序t1,由于所需资源和运行时间少,可能在很短时间内全部执行完成
}
}
}
// 两个线程同步(线程互斥)的测试类,连续两次对100减10,每减一次输出一次,区别如下:
// ThreadSynchronization1对象未锁定,两个线程随机执行,执行次数无法计数故由线程名输入,结果为 90 90,结果异常
// ThreadSynchronization2对象锁定(使用synchronized关键字),两个线程顺序执行,因为是顺序执行,所以执行次数可以累加(k),结果为 90 80,结果正常
// synchronized关键字可以用在成员方法、静态方法和代码块
class ThreadSynchronization1 implements Runnable {
private int i = 100, j = 10, ans;
@Override
public void run() {
ans = this.i - j;
// 线程休眠1秒,模拟线程异常
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.i = ans;
System.out.println("未锁定ThreadSynchronization的对象时第" + Thread.currentThread().getName() + "次减10:" + this.i);
}
}
class ThreadSynchronization2 implements Runnable {
private int i = 100, j = 10, ans, k = 1;
@Override
public synchronized void run() {
ans = this.i - j;
// 线程休眠1秒,模拟线程异常
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.i = ans;
System.out.println("锁定ThreadSynchronization的对象后第" + k + "次减10:" + this.i);
k++;
}
}
public class MultiThreading {
public static void main(String[] args) {
// 查看主线程优先级
System.out.println("--主线程的优先级为:" + Thread.currentThread().getPriority());
// MyThread、PrintRunnable类的对象实例化
MyThread mt0 = new MyThread("通过thread方法创建的线程,使用join抢先执行:线程0");
MyThread mt1 = new MyThread("通过thread方法创建的线程,使用sleep延迟执行:线程1");
MyThread mt2 = new MyThread("通过thread方法创建的线程,使用sleep延迟执行:线程2");
PrintRunnable pr1 = new PrintRunnable();
PrintRunnable pr2 = new PrintRunnable();
ThreadSynchronization1 ts1 = new ThreadSynchronization1();
ThreadSynchronization2 ts2 = new ThreadSynchronization2();
// 创建Thread类对象,参数1为:基于Runnable接口实现类的对象,参数2为:线程名
Thread t1 = new Thread(pr1, "通过Runnable接口创建的线程:线程1");
Thread t2 = new Thread(pr2, "通过Runnable接口创建的线程:线程2");
Thread tsTest1 = new Thread(ts1, "1");
Thread tsTest2 = new Thread(ts1, "2");
Thread tsTest3 = new Thread(ts2);
Thread tsTest4 = new Thread(ts2);
// 启动线程(Thread类的start方法),使线程进入可运行(Runnable)状态
mt0.start();
// 调用join方法,mt0抢占资源优先执行
// mt0.join(10); 指:mt0线程在优先执行的情况下执行10毫秒,不论是否执行完毕,都将让出自己占用的资源,退出优先状态
try {
mt0.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
mt1.start();
mt2.start();
t1.start();
t2.start();
// 设置t2的优先级最高,为10
t2.setPriority(10);
// 启动线程同步测试
tsTest1.start();
tsTest2.start();
tsTest3.start();
tsTest4.start();
}
}
一个可参考的运行结果:(为方便观察,输出结果做了空行分隔处理)
--主线程的优先级为:5
通过thread方法创建的线程,使用join抢先执行:线程0正在执行第1次
通过thread方法创建的线程,使用join抢先执行:线程0正在执行第2次
通过thread方法创建的线程,使用join抢先执行:线程0正在执行第3次
通过thread方法创建的线程,使用join抢先执行:线程0正在执行第4次
通过thread方法创建的线程,使用join抢先执行:线程0正在执行第5次
通过Runnable接口创建的线程:线程2正在执行第1次 优先级:10
通过Runnable接口创建的线程:线程2正在执行第2次 优先级:10
通过Runnable接口创建的线程:线程2正在执行第3次 优先级:10
通过Runnable接口创建的线程:线程2正在执行第4次 优先级:10
通过Runnable接口创建的线程:线程2正在执行第5次 优先级:10
通过Runnable接口创建的线程:线程1正在执行第1次 优先级:5
通过thread方法创建的线程,使用sleep延迟执行:线程1正在执行第1次
通过Runnable接口创建的线程:线程1正在执行第2次 优先级:5
通过Runnable接口创建的线程:线程1正在执行第3次 优先级:5
通过Runnable接口创建的线程:线程1正在执行第4次 优先级:5
通过Runnable接口创建的线程:线程1正在执行第5次 优先级:5
通过thread方法创建的线程,使用sleep延迟执行:线程1正在执行第2次
通过thread方法创建的线程,使用sleep延迟执行:线程2正在执行第1次
通过thread方法创建的线程,使用sleep延迟执行:线程2正在执行第2次
通过thread方法创建的线程,使用sleep延迟执行:线程1正在执行第3次
通过thread方法创建的线程,使用sleep延迟执行:线程2正在执行第3次
通过thread方法创建的线程,使用sleep延迟执行:线程1正在执行第4次
通过thread方法创建的线程,使用sleep延迟执行:线程1正在执行第5次
通过thread方法创建的线程,使用sleep延迟执行:线程2正在执行第4次
通过thread方法创建的线程,使用sleep延迟执行:线程2正在执行第5次
未锁定ThreadSynchronization的对象时第1次减10:90
未锁定ThreadSynchronization的对象时第2次减10:90
锁定ThreadSynchronization的对象后第1次减10:90
锁定ThreadSynchronization的对象后第2次减10:80