(1)线程的上一级是进程,进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。
(2)线程与进程相似,但线程是一个比进程更小的执行单位,也被称为轻量级进程。一个进程在其执行的过程中可以产生多个线程。
(3)多线程就是多个线程同时运行或交替运行。
(4)提倡多线程而不是多进程 的原因是 线程间的切换和调度的成本远远小于进程。
(5)自定义线程可以继承Thread类 ,或者 实现Runnable接口 。
(6)多进程共享数据导致脏数据,可以使用同步锁 synchronized 解决。
(7)使用 interrupt() 和 return 配合 停止线程。
(8)不是优先级低的线程就一定在优先级高的线程后面运行,而是运行的机率会低一些,,反之亦然。
(9)线程分为用户线程和守护线程 ,当 用户线程 结束后,守护线程跟着结束 ,对于自定义线程可使用方法 setDaemon(true); 设置该线程为守护线程 。
常见的 守护线程是 垃圾回收线程
(10)开启线程的方式一共三种:Thread类、Runnable接口、callable接口
package com.example.javabaisc.myThread;
import org.junit.jupiter.api.Test;
public class T1 {
@Test
public void t1(){
//调用方法一
// Mythread m = new Mythread();
// m.start();
//调用方法二
MyRunnable mr = new MyRunnable();
Thread thread=new Thread(mr);
thread.start();
System.out.println("结束");
}
}
//方法一:
class Mythread extends Thread {
@Override
public void run(){
super.run();
System.out.println("我的线程");
}
}
//方法二:
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("使用接口实现我的线程");
}
}
每个线程都有自己的实例变量count ,互不影响
package com.example.javabaisc.myThread;
import org.junit.jupiter.api.Test;
/**
* 多个线程之间不共享变量线程安全的情况
*/
public class T2 {
@Test
public void t2(){
MyThread2 m1 = new MyThread2("1");
MyThread2 m2 = new MyThread2("2");
MyThread2 m3 = new MyThread2("3");
m1.start();
m2.start();
m3.start();
}
}
class MyThread2 extends Thread {
private int count = 5;
MyThread2(String name) {
// super();
//给父类的name属性赋值
this.setName(name);
}
//每次new MyThread2只会执行一次run();
@Override
public void run() {
super.run();
while (count>0){
System.out.println("由 线程 " + MyThread2.currentThread().getName() + " 计算,剩余count=" + count);
count--;
}
}
}
/*
由 线程 1 计算,剩余count=5
由 线程 1 计算,剩余count=4
由 线程 1 计算,剩余count=3
由 线程 1 计算,剩余count=2
由 线程 1 计算,剩余count=1
由 线程 3 计算,剩余count=5
由 线程 2 计算,剩余count=5
由 线程 3 计算,剩余count=4
由 线程 3 计算,剩余count=3
由 线程 3 计算,剩余count=2
由 线程 3 计算,剩余count=1
由 线程 2 计算,剩余count=4
由 线程 2 计算,剩余count=3
由 线程 2 计算,剩余count=2
由 线程 2 计算,剩余count=1
*/
/*
每个线程都有自己的实例变量count ,互不影响
*/
package com.example.javabaisc.myThread;
import org.junit.jupiter.api.Test;
/**
* 共享数据的情况 [使用 同步锁 可解决脏数据问题]
*/
public class T3 {
@Test
public void t3() {
MyThread3 myThread3 = new MyThread3();
//参数分别是 自定义线程 ,线程名字
Thread m1 = new Thread(myThread3, "1");
Thread m2 = new Thread(myThread3, "2");
Thread m3 = new Thread(myThread3, "3");
Thread m4 = new Thread(myThread3, "4");
Thread m5 = new Thread(myThread3, "5");
m1.start();
m2.start();
m3.start();
m4.start();
m5.start();
}
}
//class MyThread3 extends Thread {
// //公共数据
// private int count = 5;
// //每次new MyThread3只会执行一次run();
// @Override
// public void run() {
// super.run();
// int yu = count--;
// System.out.println("由 线程 " + MyThread3.currentThread().getName() + " 计算,剩余count=" + yu);
//
// }
//}
/*
由 线程 3 计算,剩余count=2
由 线程 5 计算,剩余count=3
由 线程 1 计算,剩余count=5
由 线程 4 计算,剩余count=1
由 线程 2 计算,剩余count=4
*/
/*
本应该剩余count是依次递减的 ,可是显示是乱数据,
因为在大多数jvm中,count–-的操作分为如下三步:
取得原有count值
计算 -1 的结果
进行赋值
并发线程获取count的值显然是无法避免脏数据
*/
//使用锁 synchronized,即可解决线程脏数据
class MyThread3 extends Thread {
//公共数据
private int count = 5;
//每次new MyThread3只会执行一次run();
//添加了同步锁 synchronized
@Override
public synchronized void run() {
super.run();
int yu = count--;
System.out.println("由 线程 " + MyThread3.currentThread().getName() + " 计算,剩余count=" + yu);
}
}
/*
由 线程 1 计算,剩余count=5
由 线程 5 计算,剩余count=4
由 线程 4 计算,剩余count=3
由 线程 3 计算,剩余count=2
由 线程 2 计算,剩余count=1
*/
package com.example.javabaisc.myThread;
import org.junit.jupiter.api.Test;
/**
* 使用 interrupt() 和 return 配合 停止线程
*/
public class T4 {
@Test
public void t() throws InterruptedException {
MyThread4 m = new MyThread4();
m.start();
//主线程休眠0.01秒后执行
Thread.sleep(10);
m.interrupt();
Thread.sleep(1000);
System.out.println("停了么?");
}
}
class MyThread4 extends Thread {
//每次new MyThread4只会执行一次run();
@Override
public void run() {
super.run();
int i = 0;
while (true) {
//判断该线程是否被执行了interrupt()
if (this.isInterrupted()) {
System.out.println("线程被停止");
return;
}
System.out.println(i++);
}
}
}
打印结果:
setPriority不一定起作用的,在不同的操作系统不同的jvm上,效果也可能不同
数字越大优先级越高,但不是优先级低就一定在优先级高的线程后面运行,而是运行的机率会低一些,,反之亦然。
package com.example.javabaisc.myThread;
import org.junit.jupiter.api.Test;
/**
* 线程优先级对比
* setPriority不一定起作用的,在不同的操作系统不同的jvm上,效果也可能不同
* 数字越大优先级越高,但不是优先级低就一定在优先级高的线程后面运行,而是运行的机率会低一些,,反之亦然。
*
*/
public class T5 {
@Test
public void t() {
MyThread5 a = new MyThread5("A");
MyThread5 b = new MyThread5("B");
// a.setPriority(10);
// b.setPriority(1);
a.setPriority(1);
b.setPriority(10);
a.start();
b.start();
}
}
class MyThread5 extends Thread {
MyThread5(String name) {
super();
this.setName(name);
}
@Override
public void run() {
super.run();
System.out.println("我是线程:" + Thread.currentThread().getName());
}
}
注意:
不可使用@Test测试 ,否则所有线程都会随着用户线程结束而结束,看不到非守护线程运行效果
package com.example.javabaisc.myThread;
import org.junit.jupiter.api.Test;
/**
* 守护线程 ,当 用户线程 结束后,守护线程跟着结束
*
* 不可使用@Test测试 ,否则所有线程都会随着用户线程结束而结束,看不到非守护线程运行效果
*
*
*/
public class T6 {
public static void main(String[] args) throws InterruptedException {
MyThread6 a = new MyThread6();
//设置该线程为守护线程
a.setDaemon(true);
a.start();
Thread.sleep(1000);
System.out.println("用户线程结束,退出,守护线程也跟着退出");
}
}
class MyThread6 extends Thread {
private int i = 0;
@Override
public void run() {
while (true) {
System.out.println(i++);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
不设为守护线程的打印结果
设为守护线程的打印结果
手机扫一扫
移动阅读更方便
你可能感兴趣的文章