线程的创建方式,线程状态及状态转换

线程的创建方式
1.实现Runnable接口

java
  public interface Runnable{
  public abstract void run();
  }

使用步骤:
1、创建一个Runnable接口的实现类,并实现run方法
2、实例化Runnable接口实现类
3、创建Thread类实例,将实例化的Runnable实例作为参数传递
4、启动子线程,调用Thread类的实例的start

public class Runabledeom implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"主线程运行");
    }
}
       //Runable 实现类的使用
        Runabledeom runabledeom=new Runabledeom();
        Thread thread = new Thread(runabledeom,"A");
        thread.start();
        System.out.println(Thread.currentThread().getName()+" ");

2.继承Thread

public class Thread implements Runnable

Thread类是Runnable接口的实现类,实现run方法

public void run(){
if(target !=null){
target.run();
}
}
ThreadDemo threadDemo = new ThreadDemo();
threadDemo.start();

使用步骤:
1.创建类,继承Thread(extends Thread),重写run方法
2.实例化当前创建的Thread的类的子类
3.启动子线程,调用start方法
3.实现Callable接口

public interface Callable<V> {
    V call() throws Exception;
}

Callable接口提供了call方法,具有返回值,可以通过泛型来定义,该接口可以抛出异常

public interface Callable<V> {
    V call() throws Exception;
}
public class FutureTask<V> implements RunnableFuture<V>
public interface FutureTask<V> extends Runable,Future<V>{
void run();
}
//实现Callable接口
        CallableDemo callableDemo = new CallableDemo();
        //通过FutureTask可以将Callable实现类兼容成Runable实现类
        FutureTask futureTask = new FutureTask <>(callableDemo);
        Thread thread = new Thread(futureTask);
        thread.start();

使用步骤:
1.创建类,实现Callable接口,实现其提供的call方法
2.创建Callable实例
3.创建FutureTask实例,将Callable实例作为参数传入
4.创建Thread类实例,将FutureTask实例作为参数传入(当做Runnable实例)
5.调用start()方法

4.匿名类

 Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println();
        }
    });
    thread1.start();
    //在java8中通过lambda表达式
    Thread thread2 = new Thread(() -> {
        System.out.println();
    });

Runnable接口与Callable接口区别:
1.Callable接口规定的方法是call()方法,Runnable 规定的方法是run()方法
2.返回值不同,Callable的任务执行后有返回值,Runnable无返回值
3.call方法可抛出异常,run()方法不能抛出异常
4.通过运行Callable的实例可以获取到FutureTask对象,FutureTask对象表示异步执行的结果,
他提供了我们的get()方法,可以异步获取线程的执行结果(get会阻塞当前线程。call方法的返回值可以通过FutureTask的实例提供的get方法类进行获取。

***FutureTask***知识扩展:

//get方法会阻塞当前线程的执行,直至当前线程执行结束,
            // 当前线程获取到结果之后才能执行
            Object o = futureTask.get();
            //判断子线程是否被取消
            futureTask.isCancelled();
            //进行取消操作
            futureTask.cancel(true);
            System.out.println(o);

线程状态及其状态转换:

线程状态:

public enum state{
NEW,//新建状态
RUNNABLE;//就绪状态
BLOCKED,//阻塞状态
WAITING,//等待状态
TIMED_WAITING,//超时等待
TERMINATED;//终止状态
}

NEW:新建状态
用new创建的线程处于新建状态,此时和其他的java对象一样,仅仅在堆中分配了内存
RUNNABLE:就绪状态
当线程对象被创建后,一旦调用start方法,线程就处于就绪状态(其他的条件都满足),处于就绪状态的线程,
等待获取CPU的使用权。
RUNNING:运行状态
处于运行状态的线程也就占用了CPU,执行线程代码,只能从就绪状态到运行状态。
BLOCKED: 阻塞状态
阻塞状态的是指线程因为某些原因,放弃CPU(缺少资源:IO,锁),暂停停止运行,当前线程处于阻塞状态。
WAITING:等待状态
当线程处于该状态,如果某个线程中的对象调用wait(),jvm就会将线程放到等待池中。
TIMED_WAITING:超时等待
sleep(long time),join(long time)会使线程处于睡眠状态
TERMINATED(terminated):终止状态
当线程执行run()方法结尾时,就进入终止状态,表示线程的生命周期结束。
线常用方法介绍

线程生命周期:New,Runnable,Running,Terminate
线程需要相应资源时,进入阻塞状态,包含:Waiting,Blocked,Time_waiting状态

在这里插入图片描述线程常用方法介绍
start():启动线程
启动一个新线程,start方法首先调用才能创建子线程,不能重复使用

public synchronized void start() {
        group.add(this);
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
    private native void start0();//调用native方法
启动方法是需要底层OS来启动子线程,start是间接启动
JNI:java native interface,java 本地方法接口(JMM存在本地方法栈),调度系统本身提供的非java代码(c/c++)

 run():整个子线程执行的业务逻辑都在run方法中,单独调用run方法,会在当前的线程中执行run操作,不会启动子线程,可重复调用。
  public void run() {
         if (target != null) {
             target.run();
         }
     }
  Thread类中的run方法知识判断任务体Runnable是否存在,

start() 和run()方法区别?

start()是启动子线程的,start()方法启动子线程后自动的来调动run()方法
run方法是子线程的业务执行体,不能直接调用run方法,通过调用run不能启动子线程的。

yield():线程让步
是用来暂停当前执行的线程,并且让步于其他相同优先级或更高优先级的线程先执行。就绪状态的线程会按照优先级进行调整。
yield:方法在thread中,是Thread类中的静态方法。

public static native void yield();

方法特点:
1.yield方法让步CPU资源,让给由系统决定,一般是让给相同优先级或者更高优先级的线程获得执行权,没有的话,会执行原来的线程。
2.yield让步:会让当前线程由“运行状态”到“就绪状态”。
3.yield让步CPU资源后,线程不会释放锁。

join():线程合并
暂停当前线程的执行,等待子线程的执行,也叫做线程合并,join方法是将并行执行的线程合并成串行执行。
eg:在线程ta中调用tb.join,会暂停ta的执行,先让tb执行完毕,ta才会执行
方法介绍:

t.join()//允许t线程在当前线程之前执行,待t线程执行结束当前线程在执行
t.join(long millis)(时间单位:毫秒)// 允许t线程在当前线程之前执行,且最长时间millis毫秒之后,当前线程才能执行
t.join(long millis,int nanos) // 提供秒级的精度

方法特点:
1.join方法是Thread类中的方法,会抛出InterruptedException中端异常
2.当前线程ta中tb.join,tb就会执行,ta线程会进入到WAITING或TIMED_WAITING状态
3.当前线程ta中tb.join,则ta线程会释放当前持有的锁,join方法实现是通过wait/notify线程通信方式来实现的,wait方法的使用会释放锁

Q:
join方法可以使线程进行顺序执行?假如存在A,B,C三个线程,让三个线程按照C、B、A的顺序执行???

//一直等待子线程
public final void join() throws InterruptedException {
        join(0);
    }
//提供毫秒,纳秒级别的等待时间
public final synchronized void join(long millis, int nanos)
    throws InterruptedException {

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }
          //纳秒的处理最终转换为毫秒
        join(millis);
    }
 //提供毫秒级别的等待时间
public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;
          //millis等于0,会一直判断子线程是否结束,否则会一直等待
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
            //线程等待
                wait(0);
            }
        } else {
        //判断子线程是否结束且是否到达指定的毫秒数,否则会等待
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

Interrupt():中短线程
boolean isInterrupted():判断是否发生中断操作
用来中断当前线程,终止处于“阻塞状态”(WAITING/TIMED_WAITING)状态
方法介绍:interrupt():该方法在Thread类中,由对象操作方法
方法特点:
1.如果当前线程是可中断的阻塞状态(join,sleep,wait…会导致线程进入阻塞状态(WAITING/TIMED_WAITING)), 在任一的其他线程中调用interrupt()方法,会立即抛出 InterruptedException异常来停止阻塞状态。
2.如果当前是可运行状态,调用interruprt方法,线程会继续执行,直到发生了sleep等,进入阻塞状态后,随后抛出异常

public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();
        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }
private native void interrupt0();//JNI方法,终端操作由系统来提供

sleep():线程休眠
会让线程休眠,而且那个线程调用,那个线程休眠,TimeUtil.sleep(long),Thread.sleep
或当前的线程Thread.sleep,其结果都是线程休眠。
方法介绍:

sleep(long millis)sleep(long millis, int nanos)
TimeUnit.DAYS(HOURS....).sleep(long timeout)

sleep()是Thread类提供的方法,会抛出异常InterruptedException。
特点:
1.sleep休眠期间,会让出CPU的使用权,但线程仍然有锁
2.sleep休闲时间到了之后,不会立即执行,而是线程由“阻塞状态”进入到“就绪状态”

public static native void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos) throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }
        sleep(millis);
    }

deamon:守护线程
方法介绍:
boolean isDaemon()//判断是否是守护线程
setDaemon(boolean on)//设置线程为守护线程,true:守护线程

java中的线程有两种:用户线程和守护线程
用户线程和守护线程是什么?
用户线程一般用户执行的用户级的线程.
守护线程也叫做后台线程,脱离于中端,用来服务于用户线程。eg:GC是一个单独的线程来处理,是一个守护线程

守护线程的生命周期?
依赖于用户线程,有用户线程存在,守护线程就会存活,无用户线程,守护线程也会消亡。

  public final boolean isDaemon() {
        return daemon;
    }
    public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }

Priority:线程的优先级
指导线程的执行优先级
方法:

int getPriority() //获取优先级
void setPriority(int newPriority) //设置优先级

特点:
1.优先级并不绝对,它所控制的是执行的机会,即优先级高的执行的效率比较大。
2.具有继承性,如果B在A中创建,B是A的子线程,两者具有相同的优先级

优先级范围:

  public final static int MIN_PRIORITY = 1;//最小优先级
      public final static int NORM_PRIORITY = 5;//默认优先级
      public final static int MAX_PRIORITY = 10;//最大优先级
public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

    public final int getPriority() {
        return priority;
    }

线程调度(用户级调用和系统调用)
用户级调度
可以提供的调度方式:
1、调整线程优先级:Java线程有优先级,优先级高的线程获得较多的运行机会(运行时间);
static int Max_priority 线程可以具有的最高优先级,值为10;
static int MIN_PRIORIYT 线程可以具有的最低优先级,值为1;
static int NORM_PRIORITY 分配给线程的默认优先级,值为5;
Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级;
2、线程睡眠:Thread.sleep(long millins)使线程转到阻塞状态;
3、线程等待:Object.wait()方法,释放线程锁,使线程进入等待状态,
直到被其他线程唤醒(notify()和notifyAll());
4、线程让步:Thread.yeild()方法暂停当前正在执行的线程,使其进入等待执行状态,把执行机会让给相同优先级或更高优先级的线程,如果没有较高优先级或相同优先级的线程,该线程会继续执行;
5、线程加入:join()方法,在当前线程中调用另一个线程的join()方法, 则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再有阻塞状态转为就绪状态;
系统级调度
主要指系统在特定的时机自动进行调度,主要说明一下可运行状态到运行状态的调度,这个是OS的调度,主要涉及的调度算法
实时系统:
FIFO(First Input First Output,先进先出算法),
SJF(Shortest Job First,最短作业优先算法),
SRTF(Shortest Remaining Time First,最短剩余时间优先算法)。
交互式系统:
RR(Round Robin,时间片轮转算法),
HPF(Highest Priority First,最高优先级算法)。
基于时间片的优先级的调度算法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值