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

}

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

时间: 2024-08-29 10:13:20

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

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

作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39347245 本文演示,Tread多线程实现Runnable接口,以及简单的说明为什么有这种创建线程的方法. 一.创建线程的2中方法: 1)继承Thread类实现多线程,参见我的上一篇文章:Java Tread多线程(0)一个简单的多线程实例 : 2)第二种方法就是实现Runnable接口,创建一个新线程. 二.为什么要有这两种方法创建线程呢? ①主要原因:就是方法1)不

对JAVA多线程 并发编程的理解

对JAVA多线程并发编程的理解 Java多线程编程关注的焦点主要是对单一资源的并发访问,本文从Java如何实现支持并发访问的角度,浅析对并发编程的理解,也算是对前段时间所学的一个总结. 线程状态转换 Java语言定义了5中线程状态,在任何一个时间点,一个线程只能有且只有其中一种状态,这5中状态分别是: ?  新建(New):创建后尚未启动的线程处于这种状态 ?  运行(Runable):Runable包括了操作系统线程状态中的Running和Ready,也就是处于此状态的线程可能正在执行,也有可

Java的多线程 简单入门

Java的多线程 简单入门 首先可以先搞清楚什么是程序.进程.线程,以及它们之间的关系: 定义: 一 程序只是一组指令的有序集合,它是静态的 二 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位: 三 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),一个线程可以创建和撤销另一个线程: 进程与线程区别与联系 (

Java入门——多线程(一)

Java入门——多线程(一) 进程与线程的区别 进程是程序的一次动态的执行的过程,需要经历从代码的加载,代码执行到执行完毕的一个完整过程,这个过程也是进程重产生,发展到最终消亡的过程.多进程操作系统利用CPU的分时机制,分时段执行不同程序,由于CPU运行速度非常快,所以就想是多个进程同时运行一样. 线程是比进程更小的执行单位,线程在进程的基础之上进行的进一步划分.所谓多线程是指在一个进程在执行过程中可以产生多个更小的程序单元,这些更小的单元成为线程,可以同时存在,同时运行. 所谓的线程是程序的运

Java 中多线程

很多核心Java面试题来源于多线程(Multi-Threading)和集合框架(Collections Framework),理解核心线程概念时,娴熟的实际经验是必需的.这篇文章收集了 Java 线程方面一些典型的问题,这些问题经常被高级工程师所问到. 0.Java 中多线程同步是什么? 在多线程程序下,同步能控制对共享资源的访问.如果没有同步,当一个 Java 线程在修改一个共享变量时,另外一个线程正在使用或者更新同一个变量,这样容易导致程序出现错误的结果. 1.解释实现多线程的几种方法? 一

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

基础知识 每个正在系统上运行的程序都是一个进程(process).每个进程包含一到多个线程(thread).进程也可能是整个程序或者是部分程序的动态执行. 线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行.也可以把它理解为代码运行的上下文.所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务. Java对多线程的支持是非常强大的,他屏蔽掉了许多的技术细节,让我们可以轻松的开发多线程的应用程序.Java里面有2个方法实现多线程, 1 继承 Thread类,比如 class M

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

沉淀再出发:再谈java的多线程机制 一.前言 自从我们学习了操作系统之后,对于其中的线程和进程就有了非常深刻的理解,但是,我们可能在C,C++语言之中尝试过这些机制,并且做过相应的实验,但是对于java的多线程机制以及其中延伸出来的很多概念和相应的实现方式一直都是模棱两可的,虽然后来在面试的时候可能恶补了一些这方面的知识,但是也只是当时记住了,或者了解了一些,等到以后就会变得越来越淡忘了,比如线程的实现方式有两三种,线程池的概念,线程的基本生命周期等等,以及关于线程之间的多并发引起的资源的抢占

java核心-多线程(4)-线程类基础知识

1.并发 <1>使用并发的一个重要原因是提高执行效率.由于I/O等情况阻塞,单个任务并不能充分利用CPU时间.所以在单处理器的机器上也应该使用并发. <2>为了实现并发,操作系统层面提供了.但是进程的数量和开销都有限制,并且多个进程之间的数据共享比较麻烦.另一种比较轻量的并发实现是使用线程,一个进程可以包含多个线程.线程在进程中没有数量限制, 数据共享相对简单.线程的支持跟语言是有关系的.Java 语言中支持多线程. <3>Java 中的多线程是抢占式的.这意味着一个任

从jvm的角度来看java的多线程

最近在学习jvm,发现随着对虚拟机底层的了解,对java的多线程也有了全新的认识,原来一个小小的synchronized关键字里别有洞天.决定把自己关于java多线程的所学整理成一篇文章,从最基础的为什么使用多线程,一直深入讲解到jvm底层的锁实现. 多线程的目的 为什么要使用多线程?可以简单的分两个方面来说: 在多个cpu核心下,多线程的好处是显而易见的,不然多个cpu核心只跑一个线程其他的核心就都浪费了: 即便不考虑多核心,在单核下,多线程也是有意义的,因为在一些操作,比如IO操作阻塞的时候