码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2019-08-09 19:16:15      阅读:77      评论:0      收藏:0      [点我收藏+]

标签:date   port   基础   live   主程   运行时   trace   实现   string   

背景说明:

在学了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的个人理解(基础,不讲概念)

标签:date   port   基础   live   主程   运行时   trace   实现   string   

原文地址:https://www.cnblogs.com/Anxc/p/11329051.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!