Java学习日记番外篇:线程

声明:这篇文章主要内容大部分都是从林信良的Java学习日记这本书中摘录下来,仅作为个人学习参考用

1.概念

以前的程序从main()程序进入点开始到结束只有一个流程,而有的时候设计程序需要多个流程,就是多线程。

在Java中,如果想在main()以外独立设计流程,必须实现java.lang.Runnable接口,流程的进入点是操作在run()方法中。

例子:龟兔赛跑

(赛程长度为10步,每经过一秒,乌龟前进一步,兔子前进两步或者睡觉)
这里就是兔子是一个线程,乌龟是另外一个线程,最后由主函数调用这两个线程。
在Tortoise类中,乌龟的线程会从run()开始,乌龟只需要负责乌龟每秒走一步就可以,不会混杂兔子的线程。

乌龟:

package com.thread;

public class Tortoise implements Runnable
{
    private int totalStep;
    private int step;

    public Tortoise(int totalStep) //设置构造方法,传入赛程总步数
    {
        this.totalStep=totalStep;
    }

    @Override
    public void run() 
    {
        try {
            while(step<totalStep)
            {
                Thread.sleep(1000);//暂停1000毫秒,也就是1秒
                step++;
                System.out.printf("乌龟跑了 %d 步.........%n", step);//这句输出不懂
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }


}

兔子:

package com.thread;

public class Hare implements Runnable
{
    private boolean[] flags={true,false};
    private int totalStep;
    private int step;

    public Hare(int totalStep)
    {
        this.totalStep=totalStep;
    }

    @Override
    public void run() {
        try {
            while(step<totalStep)
            {
                Thread.sleep(1000);
                boolean isHareSleep = flags[(int)(Math.random()*10)%2];//判断兔子是否睡觉

                if(isHareSleep)//如果兔子睡着了,就原地不动,step就不加
                {
                    System.out.printf("兔子睡着了zzzzz");
                }
                else//如果兔子没有睡着,就一秒走两步
                {
                    step+=2;
                    System.out.printf("兔子跑了%d步....%n", step);
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


}

比赛:

package com.thread;

public class Race {

    public static void main(String[] args) {
        Tortoise tortoise = new Tortoise(10);//新建乌龟对象
        Hare hare = new Hare(10);//新建兔子对象


        Thread tortoiseThread = new Thread(tortoise);//新建乌龟对象的线程
        Thread hareThread = new Thread(hare);//新建兔子对象的线程

        tortoiseThread.start();//乌龟线程开始
        hareThread.start();//兔子线程开始



    }

}

运行结果:看样子兔子天天睡着啊= =注意,每次运行的结果不一定一致。

结果

Thread和Runnable:

事实上JVM启动以后,不只有一个主线程,还会有垃圾收集、内存管理等线程,不过这些是底层机制,单纯从编写程序的角度看JVM,就只有一个主线程。

有两种写多线程的方法:

  1. 将流程定义在Runnable的run()方法中
  2. 继承Thread类,重写run()方法。

上面的龟兔赛跑就是第一种,下面改写成第二种:

package com.thread;

public class TortoiseThread extends Thread
{
    ……
    @Override
    public void run() 
    {
        ……
}
}

下面的兔子也是一样。

然后在main()主线程中,这样写调用刚才写的线程:

new TortoiseThread(10).start();
new HareThread(10).start();

3. 线程的生命周期:

1.Daemon(伴随)线程:

如果主线程启动了额外线程,JVM会等所有线程都执行完才终止JVM,如过一个线程被标示为Daemon线程,在所有非Daemon线程都结束时,JVM就会自动停止。、

表示一个线程是Daemon线程可以这样写:实例化线程对象,然后用setDaemon方法

thread.setDaemon(true);

使用isDaemon()方法可以判断线程是否为Daemon线程。

2.Thread基本状态图:

Thread基本状态图

在调用Thread实例start()方法之后,基本状态有三种:

  • Runnable:可执行(没有真正开始运行,等待CPU分配)
  • Running:执行中
  • Blocked:被阻断

Thread.start()之后,线程进入Runnable状态,等待CPU分配。

线程看起来像是同时执行,但是事实上在同一个时间点,一个CPU只能执行一个线程,只不过CPU会不断地切换线程,而且动作很快。。。。

我们可以设定线程的优先权,使用Thread的setPriority()方法可以设定优先权,可以设置1~10,数字越大优先权越高,默认是5,如果优先权相同,就轮流执行。

有几种情况会让线程进入Blocked状态:
调用Thread.sleep()方法
等待输入/输出完成后

当某个线程进入Blocked的时候,让另一个线程排入CPU执行(成为Running状态),经常是改进效能的方式之一。

一个线程进去Blocked状态之后,可以由另一个线程调用该线程的interrupt()方法,会抛出InterruptException异常对象。:

例子:

package com.thread;

public class Interrupt {

    public static void main(String[] args) {
        Thread thread = new Thread(){

            @Override
            public void run() {
                try {
                    Thread.sleep(99999999);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    System.out.println("我醒了!!!XD");
                }
            }

        };

        thread.start();
        thread.interrupt();//主线程调用thread的interrupt()

    }

}

3.安插线程:

如果A线程正在运行,流程中允许B线程加入,等到B线程执行完毕后再继续A线程,就是安插线程。用的是join()方法。

threadB.join()//线程B join在当前线程中

可以在join()这个括号中加时间,就是这个加入的线程最多可以处理多久就要返回执行原来的线程。单位是毫秒。

5.停止线程:

一般不用。

线程后面还有很多,以后详细看。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值