【Java多线程】浅谈多线程机制(一)之初识多线程

      说起Java的多线程机制,可能很多程序猿和笔者一样,对其是又爱又恨的矛盾心理。一方面,多线程的强大功能可以简化编程模型,很方便的达到我们的目的;另一方面,也正是由于多线程的强大功能,我们很容易在编程过程中考虑不周,从而出现一些难以发现的bug。要写好Java多线程,笔者以为需要的是长期不断的练习和实践,而今天和大家分享的便是笔者在学习Java多线程中的一些感想和心得,也希望广大读者朋友批评指正。

一、初识多线程
     
1. Java对线程的支持

Java对线程的支持主要由java.lang包中封装的Thread类Runnable接口来实现。
     
2. 线程的创建和启动

创建使用Thread()方法及其重载方法,启动使用void start()方法。
     
3. 线程中其他常用的方法

(1)使线程休眠:static void sleep()及其重载函数,最低可精确到纳秒。
(2)使其他线程等待当前线程终止:void join()及其重载方法,最低等待时间可精确到纳秒。
(3)释放资源:static void yield()方法用于当前运行的线程释放占用的处理器资源。
(4)获取线程引用:static Thread currentThread() 方法用于返回当前运行线程的引用。

      关于Thread类和Runnable接口在使用上的区别,读者可以参考追寻—专栏的文章《 java线程系列—Runnable和Thread的区别》。另外,我们将在下面的实际例子中说明上述线程常用方法。

二、举例说明

      我们考虑一个学生在教室上课的实际例子:

  • 学生们是独立的个体,他们在课上的学习活动互不干扰
  • 老师是推动整堂课有序进行的关键人物
  • 教室是这堂课进行的必不可少的因素,它提供了场地

      其实上述的三句话便代表了这个实例中的三个类,分别是:学生StudentRunnable、老师TeacherThread、教室Classroom。我们通过这样的三个类便可以模拟一个简单的上课情景(以两个学生为例)。

      显然,主方法在Classroom类中定义,下面给出实现示例:

(1)StudentRunnable.java

package com.bebdong.concurrent;

//学生线程,模拟上课行为
public class StudentRunnable implements Runnable 
{

    //volatile可以保证正确读取其他线程写入的值
    volatile boolean keepRunning=true;    //回答问题直至老师叫停

    @Override
    public void run() 
    {
        while(keepRunning)
        {
            //连续回答5个问题
            for(int i=0;i<5;i++)
            {
                //getName()方法用于获取当前线程的名称
                System.out.println(Thread.currentThread().getName()+"回答第"+i+"个问题");
                Thread.yield();  //释放资源,使得其他学生也可以抢答问题
            }
        }
        System.out.println(Thread.currentThread().getName()+"回答问题结束!");
    }

}

(2)TeacherThread.java

package com.bebdong.concurrent;

//老师线程
public class TeacherThread extends Thread 
{

    public void run()
    {
        System.out.println(Thread.currentThread().getName()+"开始评判学生的回答!");

        for(int i=0;i<5;i++)
            System.out.println(Thread.currentThread().getName()+"正在评判学生的回答……");

        System.out.println(Thread.currentThread().getName()+"评判结束!");
    }
}

(3)Classroom.java

package com.bebdong.concurrent;

//教室提供上课的地点
public class Classroom extends Thread 
{

    public void run()
    {
        System.out.println("老师提问,找学生回答!");

        //老师等待学生举手回答
        try 
        {
            Thread.sleep(5000);
        } 
        catch (InterruptedException e1) 
        {
            e1.printStackTrace();
        }
        System.out.println("两个学生开始回答问题!");

        //创建两个学生
        StudentRunnable studentATask=new StudentRunnable();
        StudentRunnable studentBTask=new StudentRunnable();

        //使用Runnable接口创建线程
        Thread studentA=new Thread(studentATask, "学生A");
        Thread studentB=new Thread(studentBTask, "学生B");

        //启动线程,学生开始回答问题
        studentA.start();
        studentB.start();

        //休眠教室线程,学生专心回答问题
        try 
        {
            Thread.sleep(50);
        } 
        catch (InterruptedException e) 
        {
            e.printStackTrace();
        }

        //创建老师线程
        Thread teacher=new TeacherThread();
        teacher.setName("老师");

        System.out.println("老师要对学生回答做出正确及时的评判");

        //学生停止回答
        studentATask.keepRunning=false;
        studentBTask.keepRunning=false;

        //教室线程休眠,把资源交给老师
        try 
        {
            Thread.sleep(2000);
        } 
        catch (InterruptedException e) 
        {
            e.printStackTrace();
        }

        //教师线程运行
        teacher.start();
        //学生线程和教室线程等待老师评判
        try 
        {
            teacher.join();
        } 
        catch (InterruptedException e) 
        {
            e.printStackTrace();
        }

        System.out.println("老师评判结束,继续上课……");

    }

    public static void main(String[] args) 
    {
        new Classroom().start();
    }

}

      运行上面的程序,可以得到如下的结果:
这里写图片描述

对结果的分析和说明:

  • 由于图片是静态的,没有办法展现程序中sleep()方法的作用,读者可以试着自己运行来体会sleep()方法的作用。
  • 可以发现学生A和学生B的回答顺序是毫无规律的,这是因为调用了yield()方法释放了资源,而调度程序下次选择哪一个线程运行是不确定的。
  • 在老师评判学生的回答之前,调用了join()方法,目的是使其他线程等待老师的评判。
  • 当然,对于以上的多线程程序,每一次运行的结果可能存在些许差异,这取决于设置keepRunning属性为false时学生线程的运行状态。

      以上用多线程来模拟上课的情景或许存在不当之处,还请各位读者指正。当然读者也可以自己建立相关场景来模拟。

     (未完待续……)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值