JAVA基础22-多线程(一)【多线程的概念,线程状态及其转换】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a592381841/article/details/84844232

多线程

一.概念

         1. 进程:进程是表示资源分配的的基本概念,又是调度运行的基本单位,是系统中的并发执行的单位。

          2. 线程:单个进程中执行中每个任务就是一个线程。线程是进程中执行运算的最小单位。且线程只能属于一个线程。

         3.线程是一种轻量级的进程。

        4.线程没有地址空间,线程包含在进程的地址空间中。

         5.多线程三大特性: 原子性,可见性,有序性。

二. Java线程具有的5种状态

       新建状态(NEW):当线程对象被创建后,即进入新建状态。【Thread t=new Thread()】

       就绪状态(Runable):当线程对象调用了start方法,即进入就绪状态,等待cpu调度运行【t.start()】

       运行状态(Running) :就绪状态的线程,被cpu调度即,进入运行状态

       阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时线程进入阻塞状态;

             三种阻塞状态

                 A.等待阻塞;运行状态中线程执行了wait()方法,使得本线程进入阻塞状态

                 B.同步阻塞;线程在获取synchronized同步锁(锁被其他线程锁占有),进入同步阻塞状态

                 C.其他阻塞:线程调用了sleep(),join()或者发出I/O请求时,线程会进入阻塞状态,当sleep超时,join等待线程终止或者超时,I/O请求完成,线程会进入就绪状态

       死亡状态(Dead): 线程执行完了,或者因异常退出run()方法。

三.线程属性

     1.线程优先级

             线程范围:0-10;默认优先级为5;高优先级的线程先执行。

             默认情况下,线程是继承父类的优先级;也可通过setPriority()修改优先级。

     2.用户线程和守护线程

         用户线程:非守护线程,常规的线程

         守护线程:作用是为其他线程提供服务。只要当JVM还有用户线程,那么守护线程就会一直工作下去。例如:垃圾回收期;

         程序编写者可以设置守护线程;方法: t.setDaemon(true)

四.线程创建(NEW和Runable状态)

       1.继承Thread类,重写run()方法

package com.demo9aa.demo7;

public class ThreadA extends Thread {
@Override
public void run() {
	// TODO Auto-generated method stub
	super.run();
	int i =0;
	for(;i<10;i++){
		System.out.println(i);
	}
	
}

public static void main(String[] args) {
	ThreadA a=new ThreadA();//创建ThreadA;new状态
	a.start();//runable状态
}
}

       2.实现Runable接口,并重写该接口的run()方法

package com.demo9aa.demo7;

public class ThreadB implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		int i=0;
		for(;i<10;i++){
			System.out.println(i);
		}
	}

}

       3.使用Callable和Future接口创建线程。

            A.创建Callable接口的实现类,并实现call()方法。

            B.使用FutureTask类来包装Callable实现类的对象,

            C.此FutureTask对象作为Thread对象的target来创建线程。

package com.demo9aa.demo7;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class Demo1 {
	public static void main(String[] args) {
		//A
		Callable<Integer> c=new CallAbleA();
		//B
		FutureTask<Integer> f=new FutureTask<>(c);
		//C
		Thread r=new Thread(f);
		r.start();
	}

	
}
class CallAbleA implements Callable<Integer>{
 int i=0;
	@Override
	public Integer call() throws Exception {
		// TODO Auto-generated method stub
		for(;i<10;i++){
			System.out.println(i);
		}
		return i;
	}
	
	
} 

  五.线程让步(yield方法)

      从运行态转换为就绪态有两种情况  1.时间片用完。2.线程主动调用yield()

        yield方法作用:主动归还资源,使自己在就绪态

  六.其他阻塞(I/O请求,sleep,join)

       I/O请求:当线程开始进行I/O操作时,线程进入阻塞状态。I/O操作完成后,线程进入就绪态 

       join函数: 让一个线程等待另一个线程完成,才可以继续执行【在子线程未完成或者未超时之间,父线程进入阻塞状态;子线程完成或者超时,父线程进入就绪态】

       sleep函数:让当前正在执行的线程,暂停制定时间,并进入阻塞状态【在睡眠时间,线程进入阻塞状态,超时后,恢复到就绪态】

七.等待阻塞和同步阻塞

   A:等待阻塞 

    当正在运行时的线程(已获得锁),调用wait()方法时,线程主动放弃锁,此时线程进入 等待阻塞状态。

    B: 同步阻塞

      当正在运行的线程(未获得锁),获得锁失败(锁被其他线程锁占用),线程进入同步阻塞阶段。

      当运行线程,调用notify和notifyAll方法;此时唤醒“等待阻塞的线程“进入同步阻塞阶段。

      同步阻塞的线程,一旦获得锁,就进入就绪态。

   八.线程中断

    8-1.历史方法:  Thread有成员方法:suspend和stop都用于中断线程。 问题? ?? 线程强制中断,会导致锁永远无法归还。

    8-2.最新做法:  使用等待/通知或者给哪个线程一个中断信号,让他自己决定中断。

           8-2-1.涉及方法:             

                 interrupted()方法:  静态方法;查看当前中断信号,并其清除中断信号

                 isInterrupted()方法: 查看当前中断信号。

                 interrupt()方法:修改被调用线程的中断状态,告知那个线程,他需要被中断。

           8-2-2.详细操作如下:

              对于非阻塞线程:修改了中断状态【Thread.isInterrupted返回true】,无任何特殊现象

              对于可取消的阻塞状态的线程中:(wait,sleep,join)

                    A  线程收到中断信号后,会抛出InterruptedException;

                    B  抛出异常后会把中断状态置为true

              对于不可中断阻塞的线程中:(I/O请求时):

                   线程收到中断信息后,,他们不会抛出InterruptedException,且不会因为中断情况,而退出阻塞。

            注意:

                    尝试获取一个内部锁的操作(进入一个 synchronized 块)是不能被中断的;                     但是 ReentrantLock 支持可中断的获取模式即 tryLock(long time, TimeUnit unit)。

猜你喜欢

转载自blog.csdn.net/a592381841/article/details/84844232
今日推荐