背景说明:

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

  1. JAVA与多线程开发(线程基础、继承Thread类来定义自己的线程、实现Runnable接口来解决单继承局限性、控制多线程程并发)

    实现线程并发有两种方式:1)继承Thread类:2)实现Runnable接口. 线程基础 1)程序.进程.线程:并行.并发. 2)线程生命周期:创建状态(new一个线程对象).就绪状态(调用该对象的s ...

  2. Java Tread多线程(1)实现Runnable接口

    作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39347245 本文演示,Tread多线程实现Runnable接口,以及简单 ...

  3. java之多线程 二

    线程的生命周期: 当线程被创建并被启动时,它既不是一启动就进入了执行状态,在线程的生命周期中,它要经过new(新建),就绪(Runnable),运行(Running),阻塞(Blocked),dead ...

  4. JAVA之多线程的创建

    转载请注明源出处:http://www.cnblogs.com/lighten/p/5967853.html 1.概念 老调重弹,学习线程的时候总会牵扯到进程的概念,会对二者做一个区分.网上有较多的解 ...

  5. Java的多线程(上)

    多线程的优点和必要性是不言而喻的. 三种方法实现多线程 1. 继承Thread class A extends Thread{ public void run() {...} } 使用时, new A ...

  6. JAVA之多线程概念及其几种实现方法优劣分析

    1. 多线程 程序:指令集,静态的概念 进程:操作系统调动程序,是程序的一次动态执行过程,动态的概念 线程:在进程内的多条执行路径 Ps:单核的话进程都是虚拟模拟出来的,多核处理器才可以执行真正的多线 ...

  7. Java线程锁&分布式锁的理解及应用

    了解Java线程锁之前,先理解线程和进程的定义.进程是操作系统分配资源(CPU)的基本单位,线程是CPU执行的基本单位,一个进程可拥有多个线程,同进程间的多个线程共享分配给进程的资源.比如启动JVM时 ...

  8. Java学习---多线程的学习

    基础知识 每个正在系统上运行的程序都是一个进程(process).每个进程包含一到多个线程(thread).进程也可能是整个程序或者是部分程序的动态执行. 线程是一组指令的集合,或者是程序的特殊段,它 ...

  9. 沉淀再出发:再谈java的多线程机制

    沉淀再出发:再谈java的多线程机制 一.前言 自从我们学习了操作系统之后,对于其中的线程和进程就有了非常深刻的理解,但是,我们可能在C,C++语言之中尝试过这些机制,并且做过相应的实验,但是对于ja ...

随机推荐

  1. ReactNative: 使用AsyncStorage异步存储类

    一.简介 AsyncStorage是一个简单的具有异步特性可持久化的键值对key-value的存储系统.它对整个APP而言,是一个全局的存储空间,可以用来替代H5中提供的window属性LocalSt ...

  2. WebRTC Android版本编译

    本文简单介绍如何在Ubuntu18.04 上,编译WebRTC Android版本. 安装工具 需要用到depot_tools工具来下载webrtc源码. 安装 depot_tools git 命令获 ...

  3. 05-深入python的set和dict

    一.深入python的set和dict 1.1.dict的abc继承关系 from collections.abc import Mapping,MutableMapping #dict属于mappi ...

  4. 关联mysql失败_Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezon'

    关联mysql失败_Server returns invalid timezone. Go to ‘Advanced’ tab and set ‘serverTimezon’ 时区错误,MySQL默认 ...

  5. 简单了解一下:var 、let、const

    var 重新赋值,重新定义,作用域 属于:function scope: let 声明的变量只在 let 命令所在的代码块内有效,Block scope. const 声明一个只读的常量,一旦声明,常 ...

  6. 使用python的一些笔记

    语法 传值与传引用 Python参数传递采用的是"传对象引用"的方式.这种方式相当于传值和传引用的一种综合. 如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的 ...

  7. gradle下mybatis自动生成框架的使用

    自动生成框架的意义 主要为了解决人为添加mapper,模型等工作,减少错误,提交效率! 添加引用build.gradle configurations { mybatisGenerator } myb ...

  8. 使用 getUserMedia API获取麦克风和相机等流媒体

    概览 mediaDevices 是 Navigator 对象的只读属性,一个单列对象,可以连接访问相机和麦克风,屏幕共享等媒体输入设备 方法 enumerateDevices 请求一个可用的媒体输入和 ...

  9. netty解决粘包半包问题

    前言:开发者用到TCP/IP交互时,偶尔会遇到粘包或者半包的数据,这种情况有时会对我们的程序造成严重的影响,netty框架为解决这种问题提供了若干框架 1. LineBasedFrameDecoder ...

  10. 3、netty第二个例子,使用netty建立客户端,与服务端通讯

    第一个例子中,建立了http的服务器端,可以直接使用curl命令,或者浏览器直接访问. 在第二个例子中,建立一个netty的客户端来主动发送请求,模拟浏览器发送请求. 这里先启动服务端,再启动客户端, ...