zoukankan      html  css  js  c++  java
  • 关于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+"次");
    	}
    
    }
    
  • 相关阅读:
    CF809E Surprise me!
    2019-4-12-WPF-绑定的默认模式
    2019-4-12-WPF-绑定的默认模式
    2019-2-28-C#-16-进制字符串转-int-
    2019-2-28-C#-16-进制字符串转-int-
    2019-10-23-WPF-使用-SharpDx-异步渲染
    2019-10-23-WPF-使用-SharpDx-异步渲染
    2019-8-31-ASP.NET-Core-开启后台任务
    2019-8-31-ASP.NET-Core-开启后台任务
    2019-8-24-win10-uwp-读取文本GBK错误
  • 原文地址:https://www.cnblogs.com/Anxc/p/11329051.html
Copyright © 2011-2022 走看看