JAVA线程学习

java线程学习day01

创建线程方法

有两种方法创建线程,一是直接继承Thread,另一种是实现Runnable接口。对比这两种方法,更推荐使用实现Runnable接口方法。无论使用哪种方法,都需要重写run方法,然后将它new出来。如果是继承Thread方法创建的线程,则直接使用new出来的对象;如果是实现Runnable方法创建的线程,需要将new出来的对象做为参数创建线程。
package cn.crazy.thread;
//继承Thread的新建线程的方式
public class SecondThread {
    public static void main(String[] args) {
        //线程mt1和mt2 共享mt对象  以及mt中的i成员变量,即这两个线程共享数据和代码
        //线程继承Thread类的方式,直接new出来就行
        Thread mt1 = new MyThread2();
        Thread mt2 = new MyThread2();
        mt1.start();
        mt2.start();
    }
}
class MyThread2 extends Thread{
    int i = 0;
    @Override
    public void run() {
        for(;i<500;i++){
            System.out.println("i==="+i+"  name=="+Thread.currentThread().getName());
        }
    }
}
package cn.crazy.thread;
//实现runnable接口方式新建线程
public class FirstThread {
    public static void main(String[] args) {
        //线程t1和t2 共享mt对象  以及mt中的i成员变量,即这两个线程共享数据和代码
        //将实现runnable接口的线程类new出来,然后作为参数new一个线程
        MyThread mt = new MyThread();
        Thread t1 = new Thread(mt);
        Thread t2 = new Thread(mt);
        //调用线程对象的start启动线程,不能调用run方法,线程的run方法不能主动调用!!
        t1.start();
        t2.start();

    }
}

class MyThread implements Runnable{
    int i = 0;
    @Override
    public void run() {
        for(;i<500;i++){
            System.out.println("i==="+i+"name=="+Thread.currentThread().getName());
        }
    }

}

线程的状态以及状态转换

线程的状态

线程状态及状态转换规则具体说明如下:
(1)新建状态——就绪状态:
一个新创建的线程(使用 new+Thread 构造方法创建的对象)不会自动运行,此时
处于新建(New)状态。当程序员显式调用线程的 start()方法时,该线程进入就绪
(Runnable)状态,也称可运行状态。进入就绪状态的线程不一定立即开始运行,因为
此时计算机 CPU 可能正在运行其它的线程。可能有多个线程同时进入就绪状态,在就绪
队列中排队等候。
(2)就绪状态——运行状态:
Java 运行时系统提供的线程调度器按照一定的规则进行调度,一但某个线程获得
执行机会,则立即进入运行(Running)状态、开始执行线程体代码。
(3)运行状态——阻塞状态:
处于运行状态的线程可能因某种事件的发生而进入阻塞(Blocked)状态、暂时停
止执行。例如,线程进行 I/O 操作,等待用户输入数据。当一个运行状态的线程发生阻
塞时,调度器立即调度就绪队列中的另一个线程开始运行。
(4)阻塞状态——就绪状态:
当处于阻塞状态的线程所等待的条件已经具备,例如用户输入操作已经完成时,该
线程将解除阻塞,进入就绪状态。注意,不是恢复执行,而是重新到就绪队列中去排队。
(5)运行状态——终止状态:
线程的 run()方法正常执行完毕后,其运行也就自然结束,线程进入终止(Dead)
状态。也可以在运行过程中,非正常地终止一个线程的执行,例如调用其 stop()方法。
处于终止状态的线程不能在重新运行,因此不允许在一个 Thread 对象上两次调用
start()方法。
总体来说,就是 就绪状态,运行状态,阻塞状态,终止状态。

引起线程状态转换的几种方法

(1)sleep方法
将线程状态由 就绪–>阻塞。参数是阻塞多少毫秒。当阻塞时间结束后线程会重返就绪状态,等待CPU调用。
(2)yield方法
线程由运行状态放弃CPU,进入就绪队列,这是跟sleep的区别之一,sleep是由运行状态转换到就绪状态,二yield只是放弃了运行,并没有阻塞,而是重新进入就绪队列等待CPU的再次召唤。其实,只有比当前线程优先级高的或者相同的才有机会运行,如果没有,则该线程又会进入到运行状态。只要记住,sleep方法是线程真的去睡觉了,只要没人打扰,该多少秒就睡多少秒,绝不去抢CPU;而yield方法只是放弃CPU运行状态,进入就绪状态再次重新争抢CPU而已。
(3)interrupt方法
该方法就是设置了线程的interrupt flag(中断状态,查看源码后得知)。可以通过Thread.interrupted()方法得到当前线程的中断状态。如果线程正常运行,则什么都不会发生(仅仅发生了中断状态的改变),继续运行。但线程为阻塞状态后,则会中断阻塞状态,并抛出InterruptedException。

package cn.crazy.thread;
/*
 * 演示 sleep,yield和interrupt方法
 * sleep 和 yield 方法的区别
 * 1:sleep方法会使线程进入阻塞状态,yield会使线程进入就绪状态
 * 2:sleep不会理会线程的优先级,而yield只会让给优先级相同或较高的线程执行
 * 3:sleep方法必须显示捕获InterruptedException或者主动抛出,而yield则不用
 * 
 * interrupt方法详解
 * 该方法就是设置了线程的interrupt flag.
*/
public class Schedule {
    public static void main(String[] args) {
        Runner3 r = new Runner3();
        Thread t1 = new Thread(r);
        t1.start();
        try {
            //主线程休眠2000毫秒后调用t1的interrupt方法唤醒还在休眠的t1线程,t1线程执行完毕后,到5000毫秒时t2休眠结束,继续执行下面的代码
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();

//      Runner4 r4 = new Runner4(true);
//      Runner4 r5 = new Runner4(false);
//      Thread t3 = new Thread(r4);
//      Thread t4 = new Thread(r5);
//      //设置线程的优先级
//      t3.setPriority(5);
//      t4.setPriority(5);
//      
//      t3.start();
//      t4.start();
    }
}
//Runner3用于演示sleep方法和interrupt方法
class Runner3 implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" is sleep");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            System.out.println( "Thread interrupted..." );
        }
        for(int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()
                    +"==== No.==="+i);
        }
    }

}
//Runner4用于演示yield方法
class Runner4 implements Runnable{
    private boolean flag = false;
    public Runner4(boolean flag){
        this.flag = flag;
    }
    public void run() {
        if(flag){
            System.out.println(Thread.currentThread().getName()+" is yield");
            Thread.yield();
        }
        for(int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()
                    +"==== No.==="+i);
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值