线程:
1. 单线程与多线程的运行
public class DemoThread {
public static void main(String[] args) {
/*
TODO 构建多线程模式
方式1: 自定义类继承 Tread类并重写其run方法
在run方法中定义当前线程需要完成的任务逻辑
*/
/*
TODO 多线程的调用
1.构建对象,并直接使用其run方法运行 => 单线程运行
对于多线程的实现,不能直接使用run方法执行
2.构建对象,使用start方法进行运行 => 多线程运行
在底层会自动启动run方法,而不是在main主线程中运行run方法
*/
// run 单线程运行
MyThread myThread = new MyThread();
System.out.println("run方法没有启动...");
myThread.run();
System.out.println("run方法启动完成...");
// start 多线程运行
System.out.println("run方法没有启动...");
myThread.start(); // 启动一个新的线程用于执行当前线程对象中的run方法
System.out.println("run方法启动完成...");
}
}
// public class Thread 是一个具体的类 没有抽象方法
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("这是创建的一个新线程,定义了其中的run方法...");
}
}
}
2. 获取线程信息
public class DemoThreadName {
public static void main(String[] args) {
/*
TODO 获取线程名称
① 获取主线程的名称
② 自定义线程名称
*/
// 获取主线程信息
Thread thread = Thread.currentThread(); // 获取当前正在运行的线程对象
System.out.println("当前线程名称:" + thread.getName());
System.out.println("当前线程ID:" + thread.getId());
System.out.println("当前线程状态:" + thread.getState()); // RUNNABLE 表示正在运行
System.out.println("当前线程优先权:" + thread.getPriority());
// ThreadName threadName = new ThreadName();
// threadName.start(); // 根据自定义类启动一个单独的线程运行run方法
// threadName.start(); // TODO 注意:对于start方法 一个线程对象只能启动一次,否则会报错
new ThreadName().start(); // 根据自定义类启动一个单独的线程运行run方法
new ThreadName().start(); // TODO 每个线程对象通过start都会启动一个单独的线程,每个线程的名称都不一样
// TODO 自定义线程名
//利用构造器传入线程名
new ThreadName("张三").start();
new ThreadName("李四").start();
ThreadName threadName = new ThreadName();
//使用set方法传入线程名
//public final synchronized void setName(String name)继承自父类的setName方法
threadName.setName("王五");
threadName.start();
}
static class ThreadName extends Thread {
public ThreadName() {
}
// public ThreadName(String name) {
// this.setName(name);
// }
//super()调用父类的构造方法
public ThreadName(String name) {
super(name);
}
@Override
public void run() {
while (true) {
/*
public static native Thread currentThread();
currentThread()方法返回的是当前的Thread对象
*/
//写法一:Thread thread = Thread.currentThread(); thread.getName()
// Thread thread = Thread.currentThread();
// System.out.println("当前线程名称:" + thread.getName());
// System.out.println("当前线程ID:" + thread.getId());
// System.out.println("当前线程状态:" + thread.getState());
// System.out.println("这是自定义类中的run方法执行代码...");
//写法二:this.getName()
System.out.println("当前线程名称:" + this.getName());
System.out.println("当前线程ID:" + this.getId());
System.out.println("当前线程状态:" + this.getState());
System.out.println("当前线程优先权:" + this.getPriority());
System.out.println("这是自定义类中的run方法执行代码...");
// TODO 注意:当前sleep由于需要异常处理,但是run方法是重写父类方法,不能在方法中添加throws 异常信息
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
3. 线程优先权
public class DemoPriority {
public static void main(String[] args) {
/*
TODO:
优先权对线程执行的影响?
① 设置优先权
=> 优先级设置时需要在1-10之间 => 值越大优先级越高
注意:对于优先级高的不一定先执行,只是获取到CPU的执行权可能性更高,执行具有一定的随机性
*/
PriorityThread thread1 = new PriorityThread("张三");
//设置优先权
thread1.setPriority(1);
PriorityThread thread2 = new PriorityThread("李四");
thread2.setPriority(2);
PriorityThread thread3 = new PriorityThread("王五");
thread3.setPriority(3);
thread2.start();
thread1.start();
thread3.start();
}
static class PriorityThread extends Thread{
public PriorityThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("当前线程名称:" + this.getName());
System.out.println("当前线程优先权:" + this.getPriority());
}
}
}
}
4. 线程控制1
public class DemoThreadControl01 {
public static void main(String[] args) throws InterruptedException {
/*
TODO:
线程控制方法
① sleep 可以使当前的线程处于睡眠状态(具有倒计时的阻塞状态)
sleep(1000) => 每次执行当前线程睡眠1秒
sleep(long millis, int nanos) => 按毫秒+纳秒方式睡眠
② join 当使用该方法时,其他线程必须等待当前线程执行完成才能继续执行
③ yield 礼让线程,让当前线程退出CPU的执行权,重新竞争
*/
// join
// ControlThread thread1 = new ControlThread("李白");
// thread1.start();
thread1.join();
// ControlThread thread2 = new ControlThread("张三");
// thread2.start();
new ControlThread("张三").start();
new ControlThread("李四").start();
new ControlThread("王五").start();
}
static class ControlThread extends Thread {
public ControlThread(String name) {
super(name);
}
// sleep睡眠
// @Override
// public void run() {
// for (int i = 0; i < 10; i++) {
// if (i % 2 == 0) {
// System.out.println("当前线程名称:" + this.getName() + "遇到偶数开始睡眠....");
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
// }
// }
// }
/*
礼让线程
*/
@Override
public void run() {
for (int i = 0; i < 10; i++) {
if ("张三".equals(this.getName())) {
System.out.println("遇到张三,开始礼让");
yield();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(this.getName()+"正在执行...");
} else if ("李四".equals(this.getName())) {
System.out.println("遇到李四,开始礼让");
yield();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(this.getName()+"正在执行...");
} else {
System.out.println(this.getName()+"正在执行...");
}
}
}
}
}
5. 线程控制2
public class DemoThreadControl02 {
public static void main(String[] args) throws InterruptedException {
/*
TODO:
线程控制方法
① sleep 可以使当前的线程处于睡眠状态(具有倒计时的阻塞状态)
sleep(1000) => 每次执行当前线程睡眠1秒
sleep(long millis, int nanos) => 按毫秒+纳秒方式睡眠
② join 当使用该方法时,其他线程必须等待当前线程执行完成才能继续执行
③ yield 礼让线程,让当前线程退出CPU的执行权,重新竞争
④ setDaemon 设置当前线程为后台守护线程
当线程设置为守护线程时,如果其他所有线程执行完成,那么当前线程也会被停止 => 放入后台执行
⑤ 中断线程
public final void stop() 强制停止 => 该方法已经过时了
public void interrupt() 非强制执行,在当前线程在本次CPU执行时间片断执行完成后,再进行关闭操作
会有异常提示信息
*/
//setDaemon 设置后台守护线程
// DaemonThread thread11 = new DaemonThread("张三");
// DaemonThread thread12 = new DaemonThread("李四");
// thread11.setDaemon(true);
// thread11.start();
// thread12.start();
StopThread thread1 = new StopThread("邱六");
StopThread thread2 = new StopThread("王五");
thread1.start();
thread2.start();
}
static class DaemonThread extends Thread {
public DaemonThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("当前线程:" + this.getName() + "是否为守护线程:" + this.isDaemon());
if ("张三".equals(this.getName())) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(this.getName() + "正在执行...");
}
}
}
static class StopThread extends Thread{
public StopThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if ("邱六".equals(this.getName()) && i == 3){
//强制终止
// this.stop();
this.interrupt();//中断后会显示一个错误信息,但是并不影响程序的后续执行
}
System.out.println("当前线程:" + this.getName() + "当前i:" + i);
}
}
}
}
6. 多线程实现两人吃西瓜
import java.util.Random;
public class DemoEatWatermelonCommentVar {
public static int allNum =100;
public static void main(String[] args) {
// int allNum = 100; // TODO 如果将基本数据类型作为变量传入方法中,是直接将值赋予给方法中的变量;可以使用一个类来实现
//该方法有缺陷,还未实现多个线程对同一个变量的互斥访问,后续会发解决方案
AllWatermelon allWatermelon = new AllWatermelon();
PeopleThread thread1 = new PeopleThread("张三", allWatermelon);
PeopleThread thread2 = new PeopleThread("李四", allWatermelon);
thread1.start();
thread2.start();
}
static class AllWatermelon {
private int allNum = 100;
public void eatOne() {
allNum -= 1;
}
public int getAllNum() {
return allNum;
}
}
static class PeopleThread extends Thread {
int eatNum = 0; // 每个线程都可以维护自身的变量
Random random;
AllWatermelon allWatermelon;
public PeopleThread(String name, AllWatermelon allWatermelon) {
super(name);
random = new Random();
this.allWatermelon = allWatermelon;
}
@Override
public void run() {
while (true) {
if (allWatermelon.getAllNum() > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
eatNum += 1;
allWatermelon.eatOne();
System.out.println("当前线程:" + this.getName() + "正在吃第" + eatNum + "块西瓜," + "当前剩余的总西瓜数:" + allWatermelon.getAllNum());
if (eatNum % 13 == 0) {
System.out.println("当前线程:" + this.getName() + "吃到一颗坏瓜... 吐了...");
}
}
}
}
}
}
7. 通过实现 Runnable 接口来实现多线程模式
public class DemoRunnable {
public static void main(String[] args) {
/*
TODO
构建多线程模式
方式2: 通过实现 Runnable 接口并重写其run方法
该方式构建线程时,可以共用同一个Runnable接口的子实现类对象,这样就可以使用同一个对象中的变量
好处:
可以避免由于Java单继承带来的局限性。
适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,
较好的体现了面向对象的设计思想
*/
MyRunnableThread myRunnableThread = new MyRunnableThread();
new Thread(myRunnableThread,"线程1").start();
new Thread(myRunnableThread,"线程2").start();
}
static class MyRunnableThread implements Runnable{
int allNum = 100;
@Override
public void run() {
while (true){
if (allNum <=0){
break;
}else {
allNum -= 1;
System.out.println("当前线程:"+Thread.currentThread().getName()+"allNum:"+allNum);
}
}
}
}
}