栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

5※、线程的理解、线程的创建、通过继承Thread类实现 【线程类】、通过自定义类实现runnable接口,定义一个【可重复利用】的【任务类】 【方便线程间共享数据】【可以使用匿名内部类】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

5※、线程的理解、线程的创建、通过继承Thread类实现 【线程类】、通过自定义类实现runnable接口,定义一个【可重复利用】的【任务类】 【方便线程间共享数据】【可以使用匿名内部类】

多线程
  • 线程的理解
    • 一※、线程的创建【线程类】【任务类】【Callable】
      • 方式一:通过继承Thread类实现 【线程类】
        • 线程类的读取线程名常用方法
      • 方式二:通过自定义类实现runnable接口,定义一个【可重复利用】的【任务类】 【方便线程间共享数据】【可以使用匿名内部类】
      • 练习:【任务类】【匿名内部类】实现n的阶乘程序
      • 【任务类】获取现在对象的名字和【currentThread】获取当前执行的线程对象
    • 练习:火车票抢票【分别使用线程类和任务类来实现】
    • 方式三:通过自定义类实现Callable接口,定义一个可返回数据、可以抛出异常的执行操作
    • 三种创建方式有什么区别?分别在什么场景下应用?
    • 二※、线程的生命周期
    • 三※、线程的控制
      • 1、睡眠sleep:
      • 合并:让当前线程进入阻塞状态,直到调用join方法的线程完成之后,再回到当前线程进行操作
        • 线程合并案例1,一个和尚去挑水,另一个和尚负责下水烧饭【要挑水完成,再下水烧饭】
        • 线程合并案例2,一个和尚去挑水,另一个和尚负责下水烧饭【等待一段时间,没有等到先去扫地】
          • 实现1
          • 实现2
      • 2、让步yield:使得当前线程让出cpu,再回到就绪状态,和其他线程一起再去抢夺资源
        • 线程优先级:1-10【值越高,优先级越高,能获得更多的执行机会 】
      • 3、挂起suspend、唤醒resume:【理解即可】
      • 4、中断interrput:【理解即可】
      • 5、停止:调用stop()会结束线程和终止线程的生命周期
        • 停止线程stop()
        • 终止线程的生命周期

线程的理解

Java中的多线程:通过多并发来实现提高运行速率

–线程和进程的理解
–程序:由开发人员编写代码程序,是“死的”
–进程:由多个线程组成的,是“活的”,运行状态
–线程:接收信息的线程、发送信息的线程
由于cpu的处理能力非常强大,在人的视觉、感官来说,是觉得在同一时间上运行的(cpu会不定时让出时间片,给线程进行强占,不断的切换线程,执行不同的任务)
进程之间能不能共享同一个内存空间?不能的,每个进程都有他独自的内存空间
实现数据共享是在线程之间实现的
–独立性
–动态性
–并发性

一※、线程的创建【线程类】【任务类】【Callable】 方式一:通过继承Thread类实现 【线程类】

简单,方便使用、容易获取线程的信息

构造方法:
public Thread():分配一个新的线程对象。
public Thread(String name):分配一个指定名字的新的线程对象。
public Thread(Runnable target):分配一个带有指定目标新的线程对象。
public Thread(Runnable target,String name):分配一个带有指定目标新的线程对象并指定名字。
常用方法:
public String getName():获取当前线程名称。
public void start():导致此线程开始执行; Java虚拟机调用此线程的run方法。
public void run():此线程要执行的任务在此处定义代码。
public static void sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
public static Thread currentThread():返回对当前正在执行的线程对象的引用。
package com.daily022;

// 自定义的一个线程类,执行任务  【Thread】是Java中的线程类
// 第一种方式通过继承Thread实现线程类的定义
public class MyThread extends Thread {
    // 线程在Java中默认的工作工作方式是抢占式 【抢夺资源】而不是调用资源
    
    // 测试方法
    public static void main(String[] args) {
	// 1、创建线程对象进行
	MyThread t1 = new MyThread();
	// 2、应该先启动线程。线程去抢夺cpu,然后再执行任务
//	t1.run();// 这个是错误的启动线程的方法,这个只是调用实例化对象的方法
	// 012345678910
	
	// 正确的启动方法是; 
	// 开启线程【走完生命周期】 
	t1.start();//012345678910
    }
    // 1、在Thread中找到下面源码
    // class Thread implements Runnable {
    // 2、然后再打开Runnable方法 再查找run方法
    // public abstract void run();
    // 才发现最下面有一个run方法

    // 线程所要执行的任务
    @Override
    public void run() {
	// 实现1~10的打印输出操作
	for (int i = 0; i <= 10; i++) {
	    System.out.print(i);
	}
  }
    // 普通方法 
    // 可以理解为类里的方法
    public void run2() {
	// 实现1~10的打印输出操作
	for (int i = 0; i <= 10; i++) {
	    System.out.print(i);
	}
  }
}


线程类的读取线程名常用方法
package com.daily022;

public class MyThread2 extends Thread {

    public static void main(String[] args) {
	// 1、创建任务类的对象
	MyThread2 t1 = new MyThread2();
	// OPEN1:
	// 2、设置任务类的线程名称
//	t1.setName("线程1");
	// 3、启动线程
	t1.start();
    }

//      OPEN1
//    // 线程所要执行的任务
//    @Override
//    public void run() {
//	// 实现1~10的打印输出操作
//	for (int i = 0; i <= 10; i++) {
//	    System.out.println(this.getName() + ":" + i);
//	}
//	// OPEN1:
      线程1:0
	线程1:1
	线程1:2
	线程1:3
	线程1:4
	线程1:5
	线程1:6
	线程1:7
	线程1:8
	线程1:9
	线程1:10
//    }
    // OPEN2:
    // 线程所要执行的任务
    @Override
    public void run() {
	// 实现1~10的打印输出操作
	for (int i = 0; i <= 10; i++) {
	    System.out.println(this.getName() + ":" + i);
	}
//	Thread-0:0
//	Thread-0:1
//	Thread-0:2
//	Thread-0:3
//	Thread-0:4
//	Thread-0:5
//	Thread-0:6
//	Thread-0:7
//	Thread-0:8
//	Thread-0:9
//	Thread-0:10
    }
}

方式二:通过自定义类实现runnable接口,定义一个【可重复利用】的【任务类】 【方便线程间共享数据】【可以使用匿名内部类】

自定义任务,任务可重复利用、方便线程间共享数据
也可以使用匿名内部类的形式,用于执行一次性的任务操作

在线程类中可以轻易的得到线程的信息id、name;线程任务是完全耦合的,不能给其他线程类复用任务

在runnable任务类中不容易获取线程的信息,但是把任务进行抽离,可以多个线程复用任务

资源共享问题:
Thread中的非静态成员变量是不共享的,静态是共享的
在同一个任务类中的非静态成员变量是一样的,所以使用同一个任务的线程--资源是共享的
package com.daily022;

// 定义一个任务类, 实现Runnable接口 【可以复用】【方便线程间共享数据】
public class MyRun implements Runnable {

    public static void main(String[] args) {
	// 1、创建任务类的对象
	MyRun task = new MyRun();
	// 2、创建线程,提供任务对象
	Thread thread = new Thread(task);
	// 3、开启线程
	thread.start();
    }

    // 任务要执行的操作
    @Override
    public void run() {
	for (int i = 1; i <= 10; i++) {
	    System.out.println(i);
	 }
    }
}

练习:【任务类】【匿名内部类】实现n的阶乘程序
package com.day0805sileo;

import java.util.Scanner;

public class ThreadDemo {
    // 使用匿名内部乐力以及Runnable接口实现统计某个num的阶乘的结果【Scanner输入n】
    public static void main(String[] args) {

	// 1、 创建一个实现
	Thread thread = new Thread(new Runnable() {
	    @Override
	    public void run() {
		// -- Scanner
		Scanner sc = new Scanner(System.in);
		// 输入数值
		System.out.println("请输入一个数值m:");
		// int等于的数
		int n = sc.nextInt();
		// 结果输出为
		int result = fun(n);
		// 输出结果为
		System.out.println(n + "的阶乘结果为:" + result);
	    }

	    // 定义n的阶乘
	    public int fun(int n) {
		if (n == 1) {
		    return 1;
		} else {
		    return n * fun(n - 1);
		}
	    }
	});
	// 2、启动线程
	thread.start();
    }
}

【任务类】获取现在对象的名字和【currentThread】获取当前执行的线程对象
package com.daily022;

// 定义一个任务类, 实现Runnable接口 【可以复用】【可以用多个线程进行操作】
public class MyRun2 implements Runnable {

    public static void main(String[] args) {
	// 1、创建任务类的对象
	MyRun2 task = new MyRun2();

//	// OPEN1
//	// 设置线程名字方法一
//	// 2、创建线程,提供任务对象
//	Thread thread = new Thread(task);
//	thread.setName("线程1");
//	System.out.println(thread.getName());
//	System.out.println("线程id=" + thread.getId());
//	// 线程1
//	// 线程id=11
	
	// OPEN2
	// 设置线程名字方法二
	// 2、创建线程,提供任务对象
//	Thread thread = new Thread(Runnable target,String name);
	Thread thread = new Thread(task,"线程1");
	System.out.println(thread.getName());
	System.out.println("线程id=" + thread.getId());
	// 线程1
	// 线程id=11

	System.out.println();
	// 3、开启线程
	thread.start();
    }

    // 任务要执行的操作
    @Override
    public void run() {
	for (int i = 1; i <= 10; i++) {
//	    System.out.println(this.getName()+":"+i);// 这样不行因为Runnable接口中没有该getName方法
	    // 故此要在这里加上currentThread方法才能使用 源码为以下操作
//	    public static native Thread currentThread();
	    // currentThread()获取当前执行的线程对象
	    System.out.println(Thread.currentThread().getName()+":"+i);
//	    线程1:1
//	    线程1:2
//	    线程1:3
//	    线程1:4
//	    线程1:5
//	    线程1:6
//	    线程1:7
//	    线程1:8
//	    线程1:9
//	    线程1:10
	}
    }
}


练习:火车票抢票【分别使用线程类和任务类来实现】
           --京东
           --智行
           --飞猪

京东抢到了序号为100的火车票
智行抢到了序号为99的火车票

package com.daily022;

public class TicketMain {
    public static void main(String[] args) {
	// 【任务类】
//	TicketTask task = new TicketTask();
	// 【线程类】
	TicketThread task = new TicketThread();
	// 1、创建线程的对象
	Thread JD_COM = new Thread(task, "京东");
	Thread Intelligent_behavior = new Thread(task, "智行");
	Thread Fliggy = new Thread(task, "飞猪");
	// 2、启动线程
	JD_COM.start();
	Intelligent_behavior.start();
	Fliggy.start();
    }
}
// 【任务类】
//class TicketTask implements Runnable {
//    // 定义票数[资源共享]
//    public int nums = 100;
//
//    // 实现抢票操作
//    @Override
//    public void run() {
//	// 抢票--循环操作
//	while (nums > 0) {
//	    // 获取线程名称
//	    String name = Thread.currentThread().getName();
//	    System.out.println(name + "抢到了序号为:" + nums + "的车票");
//	    // 票数--
//	    nums--;
//	}
//    }
//}

//【线程类】
//自定义线程实现抢票操作
class TicketThread extends Thread {

    // 定义票数[资源共享-要使用静态]
    public static int nums = 100;

    public TicketThread() {
	super();
    }

    public TicketThread(String name) {
	super(name);
    }

    // 实现抢票操作
    @Override
    public void run() {
	// 抢票--循环操作
	while (nums > 0) {
	    // 获取线程名称
	    String name = this.getName();
	    System.out.println(name + "抢到了序号为:" + nums + "的车票");
	    // 票数--
	    nums--;
	}
    }
}
方式三:通过自定义类实现Callable接口,定义一个可返回数据、可以抛出异常的执行操作

–实现Callable接口、注意指定返回值类型
–使用FutureTask封装Callable接口的对象
–使用Thread类来注入FutureTask对象并创建线程
线程的结果可以通过FutureTask对象的get方法获取

–通常情况都使用Runnable方式,可以重复利用任务类对象、可以在线程间共享数据,并且可以继承其他类
–当需要在线程中返回数据和声明异常时,可以使用Callable方式

package com.day0805sileo;

import java.lang.annotation.Target;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ThreadMain {

    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
	// 1、callable接口任务
	MyCallable callable = new MyCallable();

	// 2、封装任务类的对象 FutureTask本身就是Runnable
	// public class FutureTask implements RunnableFuture {
	// public interface RunnableFuture extends Runnable, Future {
	FutureTask task = new FutureTask<>(callable);

	// 3、构建线程,提供任务类
	Thread thread = new Thread(task);
	// 4、启动线程
	thread.start();
	// 5、通过任务类来获取线程的结果
	// open1
//	Integer result = task.get();// 阻塞

//	System.out.println(task.isDone());// 任务是否已经完成

//	System.out.println(task.isCancelled());// 任务是否已经完成

	Integer result = task.get(2, TimeUnit.SECONDS);// 阻塞3
	// 阻塞时间为10s 而且阻塞这里设置的是为2s获取信息, 所以会出现报错 
	// 所以小于只要设置睡眠时间为小于2s即可 不会出现报错了
//	Exception in thread "main"
	// java.util.concurrent.TimeoutException
	System.out.println(result);

    }
}

// 定义Callable任务类 call方法
class MyCallable implements Callable {
    // 当前线程任务返回的结果 call(); [有返回值类型,可以抛出异常]
    @Override
    public Integer call() throws Exception {
	// 随机数
	Random random = new Random();
	// 设置数返回值为1
	int ran1 = random.nextInt(10);
	int ran2 = random.nextInt(10);
	// open1、2 阻塞时间(睡眠时间为10s)
	Thread.sleep(10000);

	// 返回相加的结果
	return ran1 + ran2;
    }
}

三种创建方式有什么区别?分别在什么场景下应用?


二※、线程的生命周期

–新建:创建了线程的对象,分配了内存空间
–就绪:启动了线程,进入就绪状态,等待cpu的调用
–运行:线程在运行中,执行run进行操作
–阻塞:睡眠、等待、“假死状态”

  (1)  Thread.sleep();       //引起 当前线程阻塞
   (2)  Thread.join();               //引起当前线程阻塞
   (3)  Thread.suspend();       //引起 th1 线程阻塞

–死亡:线程结束、出现异常

三※、线程的控制 1、睡眠sleep:

–Thread.sleep(1000);
–TimeUnit.SECONDS.sleep(1);
// 调用了sleep方法后,线程会进入阻塞状态,释放了cpu执行权,但是没有释放对象锁
// 睡眠结束后,会回到就绪状态,然后和其他就绪状态的线程抢夺资源

package com.day0805sileo;

import java.util.concurrent.TimeUnit;

public class TreadSleepDemo {

    // 线程睡眠操作,时间结束后,线程是回到就绪状态,重新抢夺资源
    public static void main(String[] args) throws InterruptedException {

	// 1、通过sleep方法,实现线程的睡眠(延迟)
	System.out.println("你好。。");
	// Thread..sleep(2000);//延迟2秒,单位是毫秒
	// 2、通过时间单元工具类
	TimeUnit.SECONDS.sleep(1);
	System.out.println("天气真不错。。。");
    }

}

合并:让当前线程进入阻塞状态,直到调用join方法的线程完成之后,再回到当前线程进行操作 线程合并案例1,一个和尚去挑水,另一个和尚负责下水烧饭【要挑水完成,再下水烧饭】
package com.day0805sileo;


public class JoinThreadDemo {
    // main主线程 heshang线程
    public static void main(String[] args) {
	// 创建挑水和尚线程
	HeShang heshang = new HeShang();
	// 启动线程去挑水
	heshang.start();
	try {
	    Thread.sleep(20);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	// 另一个和尚进行下水烧饭
	System.out.println("另一个和尚进行下水烧饭");
    }
}

// 定义一个线程来实现和尚去挑水的操作
class HeShang extends Thread {
    @Override
    public void run() {
	//
	System.out.println("和尚去小河挑水");
	// 模拟去挑水的时间
	try {
	    Thread.sleep(3000);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	//
	System.out.println("和尚挑水回来了");
    }
}
//这里是和main方法一起输出的
//和尚去小河挑水
//另一个和尚进行下水烧饭
//睡眠3秒时间后:和尚挑水回来了

package com.day0805sileo;

public class JoinThreadDemo {
    // main主线程 heshang线程
    public static void main(String[] args) throws InterruptedException {
	// 创建挑水和尚线程
	HeShang heshang  = new HeShang();
	// 启动线程去挑水
	heshang.start();
	try {
	    Thread.sleep(20);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	// 完成挑水(在main线程中合并heshang线程--相当于把HeShang生命周期插入main线程的生命周期)
	// heshang.join();//合并
	heshang.join(1500);// 可以设置合并的超时时间 记得抛出异常
	// 另一个和尚进行下水烧饭
	System.out.println("另一个和尚进行下水烧饭");
    }
}

// 定义一个线程来实现和尚去挑水的操作
class HeShang extends Thread {
    @Override
    public void run() {
	//
	System.out.println("和尚去小河挑水");
	// 模拟去挑水的时间
	try {
	    Thread.sleep(3000);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	//
	System.out.println("和尚挑水回来了");
    }
}
//这里是停顿1.52秒后才输出的另一个和尚进行下水烧饭
//和尚去小河挑水
//另一个和尚进行下水烧饭
//1.48秒后和尚挑水回来了


线程合并案例2,一个和尚去挑水,另一个和尚负责下水烧饭【等待一段时间,没有等到先去扫地】 实现1
package daily02;

// 线程合并案例:一个和尚去挑水、另一个和尚负责下水烧饭 [等待一段时间,没有等到则先去扫地,完成之后再下水烧饭]
public class JionThreadDemo2 {
    // main线程(主线程) HeShang线程
    public static void main(String[] args) throws InterruptedException {
	// 创建挑水和尚线程
	HeShang heshang = new HeShang();
	// 启动线程去挑水
	heshang.start();
	//
	try {
	    Thread.sleep(200);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	// 完成挑水(在main线程中合并heshang线程--相当于把heshang的生命周期插入到main中去)
//	heshang.join();// 合并
	heshang.join(1500);// 1.5秒后不等了,等待继续烧饭的时间
	// 另一个和尚进行下水烧饭
	System.out.println("等待了一段时间后,没等回来,另一个和尚去扫地");
    }
}

// 定义一个线程来实现和尚去挑水的操作
class HeShang extends Thread {

    @Override
    public void run() {
	//
	System.out.println("和尚去小河挑水");
	try {
	    Thread.sleep(3000);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}

	System.out.println("和尚挑水回来了");
	// 模拟去挑水的时间
	try {
	    Thread.sleep(3000);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	System.out.println("另一个和尚去下水烧饭。");
    }
}

实现2
package com.day0805sileo;

public class JoinThreadDemo {
    // main主线程 heshang线程
    public static void main(String[] args) throws InterruptedException  {
	// 创建挑水和尚线程
	HeShang heshang = new HeShang();
	// 启动线程去挑水
	heshang.start();
//	try {
//	    Thread.sleep(20);
//	} catch (InterruptedException e) {
//	    e.printStackTrace();
//	}
	// 完成挑水(在main线程中合并heshang线程--相当于把HeShang生命周期插入main线程的生命周期)
	// heshang.join();//合并
	heshang.join(1000);// 可以设置合并的超时时间 记得抛出异常
	while (!heshang.isDown) {
	    System.out.println("另一个和尚正在扫地。");
	    //
	    try {
		Thread.sleep(1000);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }

	}
	// 另一个和尚进行下水烧饭
	System.out.println("另一个和尚进行下水烧饭");
    }
}

// 定义一个线程来实现和尚去挑水的操作
class HeShang extends Thread {

    // 标志位
    boolean isDown = false;

    @Override
    public void run() {
	//
	System.out.println("和尚去小河挑水");
	// 模拟去挑水的时间
	try {
	    Thread.sleep(3000);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	//
	isDown = true;
	//
	System.out.println("和尚挑水回来了");
    }
}
//和尚去小河挑水
//另一个和尚正在扫地。
//另一个和尚正在扫地。
//和尚挑水回来了
//另一个和尚进行下水烧饭
2、让步yield:使得当前线程让出cpu,再回到就绪状态,和其他线程一起再去抢夺资源

this.yield();

package com.day0805sileo;

public class YelidMain {

    public static void main(String[] args) {

	// 不让步线程
	YeildThread t1 = new YeildThread();
	YeildThread t2 = new YeildThread();
	YeildThread t3 = new YeildThread();

	// 设置让步线程
	YeildThread y = new YeildThread("让步线程");
	// 启动线程
	t1.start();
	t2.start();
	t3.start();
	y.start();
	
//	【让步线程】现在在执行60步
//	【Thread-1】现在在执行60步
//	【Thread-2】现在在执行60步
//	【Thread-2】现在在执行61步
//	【让步线程】现在在执行61步
//	【Thread-0】现在在执行61步
//	【Thread-1】现在在执行61步
//	【Thread-0】现在在执行62步
//	【让步线程】现在在执行62步
//	【Thread-2】现在在执行62步
//	【Thread-1】现在在执行62步
//	【让步线程】现在在执行63步
//	【Thread-2】现在在执行63步
//	【Thread-1】现在在执行63步
//	【Thread-0】现在在执行63步
//	【Thread-2】现在在执行64步
//	【Thread-1】现在在执行64步
//	【Thread-2】现在在执行100步
//	【Thread-0】现在在执行100步
//	【让步线程】现在在执行100步
//	【Thread-1】现在在执行100步
//	【让步线程】执行让步,回到就绪状态,和其他的线程一起抢夺资源-------
//	【Thread-1】现在在执行101步
//	【Thread-2】现在在执行101步
//	【让步线程】现在在执行101步
//	【Thread-0】现在在执行101步
//	【Thread-0】现在在执行200步
//	【Thread-1】现在在执行200步
//	【让步线程】现在在执行200步
//	【让步线程】执行让步,回到就绪状态,和其他的线程一起抢夺资源-------
//	【Thread-1】现在在执行201步
//	【让步线程】现在在执行201步
//	【Thread-2】现在在执行201步
//	【Thread-0】现在在执行201步
//	【Thread-2】现在在执行202步
//	【Thread-1】现在在执行202步
//	【让步线程】现在在执行202步
//	【Thread-0】现在在执行202步
//	【Thread-1】现在在执行203步

    }
}

// 线程让步案例:如果当前线程为让步线程,并且当操作步数能够整除100时候,则当前线程执行让步【让步cpu】
class YeildThread extends Thread {
    // 定义一个步数
    public int count = 0;

    // 提供父类构造器String类型 有参数和无参数
    public YeildThread(String name) {
	super(name);
    }

    public YeildThread() {
	super();
    }

    // 重写run
    @Override
    public void run() {
	// 1、获取当前线程名称
	String name = this.getName();
	// 2、循环
	while (true) {
	    System.out.printf("【%s】现在在执行%d步n", name, count);
	    // --判断是否为让步线程,操作步数能整除100
	    if (name.equals("让步线程") && count % 100 == 0) {
		// 当前线程执行起步
		System.out.printf("【%s】执行让步,回到就绪状态,和其他的线程一起抢夺资源-------n", name, count);
		this.yield();// 让步操作
	    }
	    // count自增
	    count++;
	    // 延迟
	    try {
		Thread.sleep(20);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
	  }
   }
}
线程优先级:1-10【值越高,优先级越高,能获得更多的执行机会 】

默认优先级为5

t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(3);
t3.setPriority(3);

package com.day0805sileo;

public class YelidMain {
    public static void main(String[] args) {
	// 不让步线程
	YeildThread t1 = new YeildThread("不让步线程1");
	YeildThread t2 = new YeildThread("不让步线程2");
	YeildThread t3 = new YeildThread("不让步线程3");

	// 设置优先级
	t1.setPriority(Thread.MAX_PRIORITY);
	t2.setPriority(3);
	t3.setPriority(3);
//	【不让步线程1】现在在执行56步
//	【不让步线程3】现在在执行56步
//	【让步线程】现在在执行56步
//	【不让步线程2】现在在执行56步
//	【不让步线程2】现在在执行57步
//	【不让步线程1】现在在执行57步
//	【让步线程】现在在执行57步
//	【不让步线程3】现在在执行57步
//	【让步线程】现在在执行58步
//	【不让步线程1】现在在执行58步
//	【不让步线程3】现在在执行58步
//	【不让步线程2】现在在执行58步
//	【不让步线程1】现在在执行59步
//	【不让步线程3】现在在执行59步
//	【让步线程】现在在执行59步
//	【不让步线程2】现在在执行59步
//	【不让步线程2】现在在执行416步
//	【让步线程】现在在执行417步
//	【不让步线程2】现在在执行417步
//	【不让步线程3】现在在执行417步
//	【不让步线程1】现在在执行417步
//	【不让步线程1】现在在执行418步
//	【让步线程】现在在执行418步
//	【不让步线程3】现在在执行418步
//	【不让步线程2】现在在执行418步
//	【不让步线程1】现在在执行419步
//	【让步线程】现在在执行419步
//	【不让步线程3】现在在执行419步
//	【不让步线程2】现在在执行419步
//	【不让步线程1】现在在执行420步
//	【不让步线程2】现在在执行420步
//	【让步线程】现在在执行420步
//	【不让步线程3】现在在执行420步
//	【不让步线程3】现在在执行421步
//	【不让步线程1】现在在执行421步
//	【不让步线程2】现在在执行421步
//	【不让步线程1】现在在执行422步
//	【不让步线程3】现在在执行422步
//	【让步线程】现在在执行422步
//	【不让步线程2】现在在执行422步
//	【让步线程】现在在执行423步


	// 设置让步线程
	YeildThread y = new YeildThread("让步线程");
	// 启动线程
	t1.start();
	t2.start();
	t3.start();
	y.start();
    }
}

// 线程让步案例:如果当前线程为让步线程,并且当操作步数能够整除100时候,则当前线程执行让步【让步cpu】
class YeildThread extends Thread {
    // 定义一个步数
    public int count = 0;

    // 提供父类构造器String类型 有参数和无参数
    public YeildThread(String name) {
	super(name);
    }

    public YeildThread() {
	super();
    }

    // 重写run
    @Override
    public void run() {
	// 1、获取当前线程名称
	String name = this.getName();
	// 2、循环
	while (true) {
	    System.out.printf("【%s】现在在执行%d步n", name, count);
	    // --判断是否为让步线程,操作步数能整除100
	    if (name.equals("让步线程") && count % 100 == 0) {
		// 当前线程执行起步
		System.out.printf("【%s】执行让步,回到就绪状态,和其他的线程一起抢夺资源-------n", name, count);
		this.yield();// 让步操作
	    }
	    // count自增
	    count++;
	    // 延迟
	    try {
		Thread.sleep(20);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
	}
    }
}

3、挂起suspend、唤醒resume:【理解即可】

suspend挂起方法过时不推荐使用(偏死锁、容易造成死锁,所以不推荐使用)
resume唤醒方法过时不推荐使用

package com.day0805sileo01;

public class SuspendMain {
    public static void main(String[] args) {
	// SuspendThread
	SuspendThread t = new SuspendThread();
	t.start();
	// 睡眠时间
	try {
	    Thread.sleep(3000);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	// 突然间老师人有三急 要上厕所
	System.out.println("老师去上厕所");
	t.suspend();// 挂起点名线程 方法已经过时
	// 睡眠时间
	try {
	    Thread.sleep(1000);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	System.out.println("老师回来了,继续点名");
	// 老师回来
	t.resume();// 唤起点名线程 方法已经过时

//	老师点名:当前点到序号为:1的学生
//	老师点名:当前点到序号为:2的学生
//	老师点名:当前点到序号为:3的学生
//	老师点名:当前点到序号为:4的学生
//	老师点名:当前点到序号为:5的学生
//	老师点名:当前点到序号为:6的学生
//	老师点名:当前点到序号为:7的学生
//	老师点名:当前点到序号为:8的学生
//	老师点名:当前点到序号为:9的学生
//	老师点名:当前点到序号为:10的学生
//	老师点名:当前点到序号为:11的学生
//	老师点名:当前点到序号为:12的学生
//	老师点名:当前点到序号为:13的学生
//	老师点名:当前点到序号为:14的学生
//	老师点名:当前点到序号为:15的学生
//	老师点名:当前点到序号为:16的学生
//	老师点名:当前点到序号为:17的学生
//	老师点名:当前点到序号为:18的学生
//	老师点名:当前点到序号为:19的学生
//	老师点名:当前点到序号为:20的学生
//	老师去上厕所
//	老师回来了,继续点名
//	老师点名:当前点到序号为:21的学生
//	老师点名:当前点到序号为:22的学生
//	老师点名:当前点到序号为:23的学生
//	老师点名:当前点到序号为:24的学生
//	老师点名:当前点到序号为:25的学生
//	老师点名:当前点到序号为:26的学生
//	老师点名:当前点到序号为:27的学生
//	老师点名:当前点到序号为:28的学生
//	老师点名:当前点到序号为:29的学生
//	老师点名:当前点到序号为:30的学生

    }
}

class SuspendThread extends Thread {
    @Override
    public void run() {
	for (int i = 1; i <= 30; i++) {
	    System.out.println("老师点名:当前点到序号为:" + i + "的学生");
	    // 延迟
	    try {
		Thread.sleep(150);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
	}
    }
}
4、中断interrput:【理解即可】

调用interrupt()会打断一下线程,由于受到sleep、wait或者 join方法的影响,程序会抛出InterruptedException,异常被处理后程序会继续往下执行

package com.day0805sileo01;

public class InterrupetMain {
    public static void main(String[] args) {
	TalkThread t = new TalkThread();
	t.start();
	//
	try {
	    Thread.sleep(2500);// 当睡眠被打断的时候,就会出现InterruptedException异常
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	// 突然,孩子他妈来了,和黄爸爸有要是商谈【中断交流】
	t.interrupt();// 打断就会出现异常InterruptedException
//	java.lang.InterruptedException: sleep interrupted
//	交流结束
//	at java.lang.Thread.sleep(Native Method)
//	at com.day0805sileo01.TalkThread.run(InterrupetMain.java:30)

    }
}

class TalkThread extends Thread {
    @Override
    public void run() {
	// 开个家长会,老师和家长正在深入交流
	System.out.println("李老师,和黄爸爸在深入交流孩子的学习情况");
	// 根据交流的时间
	try {
	    Thread.sleep(5000);
	} catch (InterruptedException e) {
//	    e.printStackTrace();
	    System.out.println("交流被打断,然后改日再聊!");// 预处理操作
	}
	// 输出结果
	System.out.println("交流结束");
    }
}

5、停止:调用stop()会结束线程和终止线程的生命周期

后台线程:也称为守护线程,主要做一些幕后工作,比如jvm的垃圾回收机制;后台线程和普通线程的创建方式是一样的,但是要使用thread.setDaemon(true)进行设置
注意:后台线程的生命周期和主线程的生命周期是一致的、绑定的;当主线程死亡,则后台线程也跟着死亡

停止线程stop()
package com.day0805sil02;

public class StopDemo {
    public static void main(String[] args) {
	TalkThread t = new TalkThread();
	t.start();
	//
	try {
	    Thread.sleep(2500);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	t.stop();// 停止线程、结束线程
	// 李老师,和黄爸爸在深入交流孩子的学习情况
    }
}

class TalkThread extends Thread {
    @Override
    public void run() {
	// 开个家长会,老师和家长正在深入交流
	System.out.println("李老师,和黄爸爸在深入交流孩子的学习情况");
	// 根据交流的时间
	try {
	    Thread.sleep(5000);
	} catch (InterruptedException e) {
//	    e.printStackTrace();
	    System.out.println("交流被打断,然后改日再聊!");// 预处理操作
	}
	// 输出结果
	System.out.println("交流结束");
    }
}

终止线程的生命周期

注意:后台线程的生命周期和主线程的生命周期绑定的,主线程死亡,后台线程也跟着死亡

package com.day0805sil02;

public class DaemonMain {
   
    public static void main(String[] args) throws InterruptedException {
	// 创建线程
	DaemonThread damon = new DaemonThread();
	// 设置为后台线程
	damon.setDaemon(true);
	// open1启动线程
	damon.start();// 后台线程执行数据检测操作。。。
	// open2主线程执行5秒
	Thread.sleep(5000);
//	后台线程执行数据检测操作。。。
//	后台线程执行数据检测操作。。。
//	后台线程执行数据检测操作。。。
//	后台线程执行数据检测操作。。。
//	后台线程执行数据检测操作。。。
    }
}

// 后台数据检测工作
class DaemonThread extends Thread {
    @Override
    public void run() {
	while (true) {
	    System.out.println("后台线程执行数据检测操作。。。");
	    //
	    try {
		Thread.sleep(1000);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
	  }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1035301.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号