Thread类基本用法
线程创建(5种)
1.继承Thread类 重写run方法
/**
* 多线程代码 创建1
* 继承Thread类 重写run方法
*/
class MyThread extends Thread{
@Override
public void run(){
while(true){
System.out.println("my thread!!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Demo1 {
public static void main(String[] args) {//main也是一个线程(主线程)
MyThread t = new MyThread();
t.start();//真正创建了一个新线程 线程和线程要完成的工作耦合在了一起
//t是线程 要完成的工作是run
while(true){
System.out.println("main thread!!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
2.实现Runnable接口 重写run方法
/** 多线程代码 创建2
* 实现Runnable 接口 重写run方法
* 将线程要完成的工作和线程本身分开
* 解耦合
*/
class MyRunnable implements Runnable{
@Override
public void run() {
while(true){
System.out.println("my thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Demo2 {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread t = new Thread(runnable);//runnable是线程要完成的工作
t.start();//t是线程 也是这里真正创建了一个线程
while(true){
System.out.println("main thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
3.匿名内部类 继承Thread类
/** 多线程代码 创建3
* 匿名内部类 实现创建Thread子类的方式
*/
public class Demo3 {
public static void main(String[] args) {
//创建一个Thread的子类 同时实例化对象
Thread t = new Thread(){//是匿名的 也是一个内部的类(在Demo3里)
@Override
public void run(){
while(true){
System.out.println("my thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
};
t.start();
while(true){
System.out.println("main thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
4.匿名内部类 实现Runnable接口
/** 多线程代码 创建
* 匿名内部类 实现 实现Runnable接口的方式
*/
public class Demo4 {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
//Runnable 匿名内部类的示例,作为构造方法传参
@Override
public void run() {
while(true){
System.out.println("my thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
t.start();
while(true){
System.out.println("main thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
5.lambda表达式
/** 多线程代码 创建5
* lambda表达式 本质是一个匿名函数
*/
public class Demo5 {
public static void main(String[] args) {
// ()函数的形参 {}函数体
Thread t = new Thread(() -> {
while(true){
System.out.println("my thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
while(true){
System.out.println("main thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
线程中断
使用interrupt()来中断线程,标志位为true
class Demo{
public static void main(String[] args) {
MyRunnable1 runnable1 = new MyRunnable1();
Thread t = new Thread(runnable1,"zhangyanzhe");
t.start();
t.interrupt();//在主线程中使用interrupt来中断线程,设置标志位,标志位为true
}
}
class MyRunnable1 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().isInterrupted());
//判断是否设置了标志位
//按下开关后不弹起,不清除标记位,标志位一直为true
System.out.println(Thread.interrupted());
//判断是否设置了标志位
//按下开关后弹起,也就是清除标记位,只打印一次ture剩下都是false
}
}
}
线程等待
如果线程对象是t,线程中断使用 t.join(),可以使主线程(main线程)堵塞,等待t线程执行完后,再执行主线程,join有一个不带时间的参数,和一个带时间的参数,根据需求使用,不过基本用的都是带时间的,不无限等待,比如你进游戏或者卡住了,到一定时间没响应就会给你一些选择关闭还是继续等待,或者自动强制结束。
public class Demo5 {
public static void main(String[] args) throws InterruptedException {//处理异常
// ()函数的形参 {}函数体
Thread t = new Thread(() -> {
while(true){
System.out.println("my thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
t.join();//join是一个线程不安全的操作 只要是线程不安全的,idea都会报异常 只要处理一下就好了
while(true){
System.out.println("main thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
如果不使用join,两个线程都会执行
使用了join后,会堵塞主线程,先执行完t线程,因为t线程是一个无限循环,所以会一直执行t线程
线程休眠
创建线程会用PCB来描述和控制线程,操作系统又会通过数据结构的双向链表来控制PCB的删除和创建,线程休眠使用 t.sleep.() 括号里是堵塞时间,单位ms,可以让这个线程t堵塞一段时间,操作系统会有两个链表,一个是就绪链表,一个是堵塞链表,就绪链表中的PCB会上cpu执行,堵塞链表则是等待,如果sleep这个线程,就会让他从就绪链表到堵塞链表中去,等sleep时间结束,再把它调度回就绪链表中去,但它回到了就素链表中并不是直接执行而且看系统调度会不会调度到它,一般时间会比写的那个时间稍微多几ms,因为调度回就绪链表也是会花费时间的。
public class Demo5 {
public static void main(String[] args) {
// ()函数的形参 {}函数体
Thread t = new Thread(() -> {
while(true){
System.out.println("my thread!");
try {
Thread.sleep(1000);//休眠操作,不安全,所以要处理异常
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
while(true){
System.out.println("main thread!");
try {
Thread.sleep(1000);//休眠操作,不安全,所以要处理异常
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
获取线程的实例
Thread thread = Thread.currentThread();//获取当前线程的实例
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("1");
}
},"自己的线程");//给线程一个名字
t.start();
System.out.println(t.getName());//自定义线程
Thread thread1 = Thread.currentThread();//获取线程的实例
System.out.println(thread1.getName());//主线程 main
System.out.println("2");
}
}