多线程-三状态的转换_调度

多线程

使用多线程可以让程序充分利用CPU资源,提高CPU的使用效率,从而解决高并发带来的负载均衡问题。

优点:

  • CPU资源得到更合理的利用。

  • 程序设计更加简洁。

  • 程序响应更快,运行效率更高。

缺点:

  • 需要更多的内存空间来支持多线程。

  • 多线程并行访问的情况可能会影响数据的准确性。

  • 数据被多线程共享,可能出现死锁的情况。

重点:线程状态,线程调度,线程同步,高并发与线程池,实战为主。

进程

是指计算机在某个数据集合上进行的一次运行活动,是系统进行资源分配调度的基本单位。简单理解,进程就是计算机正在运行的一个具体的应用程序。

线程是进程的基本单位,程序执行的最小单元,为独立完成程序中的某个功能而存在,一个进程是由一个或者多个线程组成的。

进程和线程的区别

进程在运行时拥有独立的存储空间,每个进程所占用的内存都是独立的,互不干扰。

多个线程是共享内存空间的,每个线程都有其执行的入口和出口,但是线程不能独立执行,必须依赖于进程,由进程提供多线程的执行控制。

多线程:在一个进程中,多个线程同时执行。

### Java中线程的使用

  • 继承Thread类

  • 创建自定义类并继承Thread

  • 重写Thread的run方法,并编写该线程的业务逻辑代码

1.自定义一个线程类,继承Thread类,重写父类的run方法,完成自定义线程的具体的业务逻辑。

定义好了⼀个线程类之后,我们就可以通过该类来实例化对象,对象就可以描述⼀个线程。实例化该对象之后,必须通过调⽤start()来开启该线程,这样该线程才会和其他线程来抢占CPU资源,不能调⽤run()⽅法,调⽤run()相当于普通的实例对象⽅法调⽤,并不是多线程。

使用:实例化自定义线程类的对象,该对象就是一个线程对象,然后启动线程即可。

public class MyThread extends Thread{
	//自定义线程的具体的业务逻辑
    public void run(){
        dosomething...
    }
}

//使用
MyThread myThread = MyThread();
myThread.start();

2.自定义一个类,实现Runnable接口,实现接口的run方法,完成自定义线程的具体业务逻辑。

使用:实例化实现类的对象,但是它并不是一个线程对象,它只是实现了线程要执行的业务逻辑,还需要实例化一个线程对(Thread),将实现类对象传给线程对象,就会覆盖线程对象继承自父类的run方法,完成自定义的业务逻辑。

//自定义Runnable实现类
public class MyRunnable implements Runnable{
	//自定义线程要执行的具体的业务逻辑
    public void run(){
        dosomething...
    }
}

//使用
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();



new Thread(new Runnable() {
    @Override
    public void run() {
        for (int i = 100; i < 200; i++) {
            System.out.println(i);
        }
    }
}).start();

线程的状态

1.创建状态:一个线程对象被实例化之后。

2.就绪状态:创建好的线程对象调用了start方法启动之后。

3.运行状态:当前线程对象获取了CPU资源,可以执行其业务逻辑代码(run方法的代码)。

4.阻塞状态:运行状态的线程进行了休眠或其他操作导致线程暂停执行。

5.死亡状态:线程执行完毕或者因为异常退出。

在这里插入图片描述

线程礼让与线程休眠的区别:休眠指从运行状态进入阻塞状态----礼让即从运行状态或就绪状态来到阻塞状态

线程调度

  • 线程休眠

休眠指让当前线程暂停执行一段时间,从运行状态进入阻塞状态,将CPU资源让给其他线程的一种调度方法,通过sleep方法来实现,sleep(long millis)是java.lang.Thread类中定义的方法,使用时需要指定当前线程休眠的时间,单位为毫秒(1000毫秒=1秒)。

package com.m.test;


public class Class02 {

	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		try {
            //Thread.sleep(3000);
			myThread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		myThread.start();
	}
}


public class MyThread extends Thread{
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			if(i == 5) {
				try {
					sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println(i);
		}
	}
}

mian线程进行休眠操作


package com.m.test;

public class Class02 {

	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			if (i == 5) {
				try {
					Thread.currentThread().sleep(3000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			System.out.println(i);
		}
	}
}

  • 线程合并

合并的意思是将指定的某个线程合并到当前线程中,将原本两个交替执行的线程改为顺序执行,即一个线程执行完毕之后再来执行第二个线程,通过调用线程对象的join方法来实现合并。

具体如何来实现合并?谁为主谁为从?假设有两个线程:线程a,线程b。

线程a在执行到某个时间点的时候调用了线程b的join方法,则表示从当前时间点开始CPU资源被线程b独占,线程a进行阻塞状态,直到线程b执行完毕,线程a重新进入就绪状态,等待获取CPU资源进入运行状态继续执行。

package com.m.test;



public class Class01 {
	public static void main(String[] args) {
		JoinRunnable joinRunnable = new JoinRunnable();
		Thread thread = new Thread(joinRunnable);
		thread.start();
		for (int i = 0; i < 100; i++) {
			if(i == 10) {
				try {
//					thread.join(3000);
                    thread.join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println(i+"Test---------------------");
		}
	}
}

public class JoinRunnable implements Runnable{

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				Thread.currentThread().sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(i+"+++++++++++++++++++JoinRunnable");
		}
	}
	
}

注意:同样是完成线程合并的操作,join()和join(long millis)是有区别的,join()表示被调用线程执行完成之后才能释放CPU资源,让其他线程来执行,join(long millis)则表示被调用的线程执行millis毫秒之后,无论其是否执行完毕,其他线程都可以和它来争夺CPU资源。

  • 线程礼让

线程礼让是指在某个特定的时间点,让当前线程暂停抢占CPU资源的行为,即从运行状态或就绪状态来到阻塞状态,从而将CPU资源让给其他线程来使用。假如有线程a和线程b在交替执行,某个时间点线程a作出了礼让,所以在这个时间点线程b就拥有了CPU资源,执行其业务逻辑,但不是说线程a会一直暂停争夺,线程a只是在特定的时间节点进行礼让,一旦过了这个时间节点,线程a在此进入就绪状态,和线程b来争夺CPU资源。

通过调用线程对象的yield方法来完成礼让。

  • 线程中断

比如:下载资源,取消下载。

Java中实现线程中断机制有如下几个方法:

public void stop() 粗暴的方式

public void interrupt()

public boolean isInterrupt()

stop()方法在新版本的JDK已经不推荐使用了,interrupt是一个实例方法,当一个线程对象调用该方法时,表示中断当前线程对象。

每一个线程都有一个标志位来标识当前线程对象是否为中断状态,isInterrupt()方法就是用来获取当前线程对象的标志位的,true表示清除了标志位,当前线程对象已经中断,false表示没有清除标志位,当前线程对象没有中断。

总结:

线程调度:
1、线程休眠(sleep):让当前线程对象暂停执行,从运行状态进入阻塞状态,将
CPU资源让给其他线程的一种调度方式。
2、线程合并(join):线程甲在某个时刻调用了线程乙的join,从这一时刻开始,
CPU资源完全被线程乙占用,直到线程乙的任务执行完毕,将CPU资源释放,
线程甲才能继续执行。
3、线程礼让(yield):让当前线程在某一个时刻让出CPU资源,仅仅是在这一时刻进行
礼让,在下一个时刻会继续争夺CPU资源。
4、线程中断(interrupt):
线程中断有三种方式:
1.线程的任务执行完毕,自动关闭。
2.线程执行过程中,因为抛出异常导致线程中断。
3.根据需求手动进行中断。






备注:最近来手感,写了个类似Tomcat服务

github地址:https://github.com/cnamep001/my_tomcat.git






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值