关于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+"次");
	}

}
posted @ 2019-08-09 18:41  Anxc  阅读(1459)  评论(2编辑  收藏  举报