关于Java的多线程Runnable的个人理解(基础,不讲概念)

Posted anxc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Java的多线程Runnable的个人理解(基础,不讲概念)相关的知识,希望对你有一定的参考价值。

背景说明:

在学了Java的多线程(继承Thread,Runnable)以后,我出于好奇,就想知道java到底是不是多线程的,不能它说自己是多线程就是多线程,自己想验证一下,于是我就想测试一下,但继承Thread由于java的单继承形式,导致不能生成多线程,但是Runnable可以,于是我就做了一个脚本(个人感觉一个java文件就是一个脚本,没有上升到项目级别),我同时生成了10个线程,来模拟购票系统,假设一个线程模拟一个人去购10张票,一个人购买一张票的时间是0.5s(不可同时去购买两张票及以上),然后观察这100张票用多少时间购买完成。

所遇到的问题1:

问题描述:

首先就是计算一共用了多少时间了,我利用了如下图的代码框架来编写,发现一个问题:因为当前java主程序也是一个线程,当主java程序在运行时,在创建完这10个线程后,主Java程序就执行完成了,它不会管这10个线程是否运行完成,在时间计算时,出现了问题。总时间会在线程运行时输出(输出的时间不是线程运行的时间)
技术图片

解决步骤1:

解决方案如图,解释一下:我在接口实现类中定义了一个线程静态共享变量,这个时候,当10个线程创建成功并运行,在最后一个线程运行完毕是对endTIme进行最后一次修改,该endTime就是这十个线程最后运行完成的时间,再进行时间计算。问题也就来了,还是没有解决时间的统计,因为java主程序还是一个线程,时间输出错误。
技术图片

解决步骤2:

考虑到java主程序也是一个线程,我在创建10个线程后,立即休眠java 主线程(提前预估时间并设置相应的休眠时间),休眠时间稍微比线程运算预估时间大一点
技术图片

最后:

时间问题解决,但是这个时候引发了一个大的问题,当10个线程在访问同一个数据并修改时,数据可能发生异常。这个时候就需要线程对数据的互斥机制。

代码:

主程序java代码:javaThreadTest

package org.axc.com.javathread;

import java.util.Scanner;

/**
 * 
    * @ClassName: javaThreadTest
    * @Description: 测试java线程的运行
    * @author Anxc
    * @date 2019年8月8日
    *
 */
public class JavaThreadTest 
    public static void main(String[] args) 
//      线程的创建
        MyThread mythread;
        
        System.out.println("---------继承Thread方式来实现创建线程-----------------");
        Scanner in = new Scanner(System.in);
        String menu="线程测试开始";
        int chioce=1;
        
        while(chioce!=0) 
            
            mythread = new MyThread();
            System.out.println("请输入非0来开始调试继承的Thread");
            System.out.print(">>");
            chioce = in.nextInt();
            if(chioce==0) 
                System.out.println("ByeBye");
                break;
            
//          输出菜单
            System.out.println(menu);
            
//          线程运行
            mythread.start();
        
        
        System.out.println("------------利用Runnable接口实现创建线程-------------");
//      测试Runnable的多线程所用时间
        chioce = 1;
//      利用Runnable接口,初始化线程
        Runnable runnable = new MyRunnable();
        long startTime;
        long endTime;
        
        while(chioce!=0) 
            System.out.println("请输入非0来开始调试");
            System.out.print(">>");
            chioce = in.nextInt();
            if(chioce == 0) 
                System.out.println("Runnable ByeBye!");
                break;
            
            startTime = System.currentTimeMillis();
            System.out.println(startTime);
//          创建10个线程来观察是否是真的多线程运行
            new Thread(runnable).start();
              new Thread(runnable).start();
              new Thread(runnable).start(); 
              new Thread(runnable).start(); 
              new Thread(runnable).start(); 
              new Thread(runnable).start(); 
              new Thread(runnable).start(); 
              new Thread(runnable).start(); 
              new Thread(runnable).start(); 
              new Thread(runnable).start();
              
              Thread t=new Thread(runnable);
              //t.isAlive();//判断线程是否存活
             try 
                Thread.sleep(8000);
             catch (InterruptedException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
//          输出最后所用时间
            System.out.println("最终所用时间为:"+(((MyRunnable) runnable).getEndTime()-startTime));
        
    

实现接口Runnable的java程序代码:MyRunnable

package org.axc.com.javathread;

/**
 * 
    * @ClassName: MyRunnable
    * @Description: 测试Runnable的真正多线程
    * @author Anxc
    * @date 2019年8月8日
    *
 */
public class MyRunnable implements Runnable 
    private static int count=100;    //加互斥锁,当一个线程去修改值时,其它线程不能读取
    public static long endTime;
    private static boolean flag=true;
    
    public MyRunnable() 
        
    

    @Override
    public void run() 
        
        int num=10;
//      加锁,使修改变量时只有一个线程在操作
        while(num>0) 
            if(flag) 
                flag=false;//加锁
            count--;
            // TODO Auto-generated method stub
            System.out.println("当前剩余"+count);
            flag=true;//关锁
            
            else 
                try 
                    Thread.sleep(10);
                 catch (InterruptedException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                continue;
                
            
            try 
                Thread.sleep(500);
             catch (InterruptedException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
            num--;
        
        
//      获取线程运行终止时间
        endTime = System.currentTimeMillis();
//      System.out.println(endTime);
    
    
    public long getEndTime() 
        return endTime;
        
    

继承Thread的方法的java程序:MyThread

package org.axc.com.javathread;

/**
 * 
    * @ClassName: MyThread
    * @Description: java线程的实现方式之一继承Thread
    * @author Anxc
    * @date 2019年8月8日
    *
 */
public class MyThread extends Thread 
    private static int count = 0;
    public void run() 
        
        int num=0;
        count++;
        while(num<5) 
            System.out.println("再等等!"+count+num);
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
            num++;
        
        System.out.println("当前已经累计运行该线程:"+count+"次");
    

以上是关于关于Java的多线程Runnable的个人理解(基础,不讲概念)的主要内容,如果未能解决你的问题,请参考以下文章

多线程系列之 关于Java多线程的个人理解

java 创建线程问题 在线等待!

Java基础加强之并发常用的多线程实现方式

Java中的多线程如何理解——精简

java笔记Java中的多线程

JAVA采用实现Runnable接口的多线程技术,用50个线程,生成10000个[1-1000]间的随机整数。