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

    xiaoxiao2021-03-25  65

          说起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时学生线程的运行状态。

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

         (未完待续……)

    转载请注明原文地址: https://ju.6miu.com/read-33839.html

    最新回复(0)