线程和进程的基本概念

进程和线程是动态的概念。

        进程是 “执行中的程序“,是一个动词,而程序是一个名词,进程运行中程序的”代码“,而且还有自己的计数器,寄存器,它会向系统申请系统资源。

        线程是进程中的一个控制流。一个程序可能可能包含多个任务并发运行,而线程就是指一个任务重头到尾的执行流。

        说的在简单点,线程是执行中的任务,一个程序包含多个任务。

 

多线程

       单处理器中,为提高处理器的使用率(最终目标),使得程序在进行IO输入出等不需要处理器时,也能够让处理器在运转,引进多线程处理机制。多线程可以使得程序运行的更快,执行效率更高,交互性更强,这是不言而喻的!

 

创建任务和线程

        一个任务是一个对象,所以为创建一个任务,必须定义一个类,定义一个任务类,为了说明这是一个任务类,它需要实现Runnable接口,这个接口只包含一个run方法。

当我们定义好任务类taskClass之后,就可以用它的构造方法创建一个任务啦:TaskClass  task = new TaskClass(.....);

        我们创建的任务只能在线程中运行,Thread类中包含了创建线程以及控制线程的众多方法。使用下面的语句创建任务线程:Thread  thread  = new Thread(task);

        然后调用start()方法告诉java虚拟机该线程准备运行:thread.start();之后java虚拟机通过调用任务的run()方法执行任务。

 

事例代码:

public class TaskThreadDemo{
public static void main(String[] args)
{
//创建任务 并且需要为任务 创建 任务类,使用该类的构造方法创建任务
PrintChar printA = new PrintChar('a',100);
PrintChar printB = new PrintChar('b',100);
PrintNum print100 = new PrintNum(100); //为任务创建线程
Thread thread1 = new Thread(printA);
Thread thread2 = new Thread(printB);
Thread thread3= new Thread(print100); //告诉虚拟机器线程开始运行
thread1.start();
thread2.start();
thread3.start();
}
} class PrintChar implements Runnable
{
private char charToPrint;
private int items; public PrintChar(char c,int t)
{
charToPrint = c;
items = t;
} @Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<items;i++)
{
System.out.print(charToPrint);
}
}
} class PrintNum implements Runnable
{
private int lastNumb;
public PrintNum(int n)
{
lastNumb = n;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i= 1;i<100;i++)
{
System.out.print(" "+lastNumb);
}
}

}

 

 

一个好玩的闪烁文本框,直接用线程,不用main方法

import javax.swing.JApplet;
import javax.swing.JLabel;
public class FlashingText extends JApplet implements Runnable {
private static final long serialVersionUID = 1L;
private JLabel jlbText = new JLabel("Welcome",JLabel.CENTER); public FlashingText()
{
add(jlbText);
new Thread(this).start();
} public void run()
{
try {
while(true)
{
if(jlbText.getText()==null)
jlbText.setText("Welcome");
else
jlbText.setText(null);
Thread.sleep(200);
}
} catch (Exception e) {
// TODO: handle exception
}
}
}

 

 

Thread类

        Thread类实现了Runnable接口,它包含为任务而创建线程的构造方法,以及控制方法,下图就是Thread类常见的控制线程的方法:

          因为Thread类实现了Runnable接口,所以可以定义一个Thread的扩展类,里面实现run方法,这样也可以创建一个线程类,但并不是很推荐这种方法,因为它将创建任务和运行任务的机制混在了一起,将任务从线程中分离出来比较好,即尽量使用Runnable接口创建线程,这样得到的线程更加灵活,避免了java单继承带来的局限性。

 

线程池

           线程池是管理并发执行任个数的理想方法,java提供Executor接口来执行线程池中的任务,提供ExecutorService接口来管理和控制任务。为了创建Executor接口实例,我们可以用Executors类,Executors类提供了创建Executor接口对象的静态方法,下图描述了上面的上面所说的关系。

 

       线程池中的shutdown()方法一般都是放在main方法的后面部分,当所以的线程都添加到线程池中,即便有线程没有执行完毕,也可能会关闭线程池,未执行完的线程继续执行,所以main方法可能比子线程先结束。

利用isTerminated()进行线程池中所有线程运行时间的统计

       倘若希望主线程在子线程全部做完之后在执行,可以考虑让所以的子线程用jion方法,但这可能导致所有子线程变成串行,不是很好的办法,当然我们也可以多线程的辅助类CountDownLatch,这是一个与计时器有点类似功能的类。这次在看书学习的时候,发现了一个更好的办法,就是在shutdown()方法后加上一句while(!executor.isTerminated()){},这是一个不错的方法(不过我把shoudown()方法放在该while语句后面,就会陷入死循环,应该是要先关闭线程池,在判断线程池中的线程是否全部终止,因为也有可能在while语句后面在添加新的子线程)。

       isTerminated()方法:如果线程池中所以线程都已完成并终止,则返回true.

       可以使用CountDownLatch 和上面的方法对程序运行计时统计,不过我记得CountDownLatch类是需要指定线程的个数。

事例代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorDemo {
public static void main(String[] args){
long start = System.currentTimeMillis();
System.out.println("当前时间"+" "+start);
ExecutorService executor = Executors.newFixedThreadPool(4); executor.execute(new PrintChar('a',100));
executor.execute(new PrintChar('b',100));
executor.execute(new PrintChar('c',100));
executor.execute(new PrintNum(100)); executor.shutdown();
while(!executor.isTerminated()){
//System.out.print("-");
}; long end = System.currentTimeMillis();
System.out.println("\n当前时间"+" "+end);
System.out.println("\n用时"+" "+(end-start)+"毫秒");
}
}
 
运行截图
截图1      截图2

         不过不知道运行太快的原因,还是啥别的原因, 会出现截图2的情况,网上很少关于isTerminated()方法的介绍,如有大神知道原因,还请告知小弟。

 

         这篇博客是自己在学习《java语言程序设计进阶篇》时所在笔记,代码出自书上,最后那个记时的加了计时部分。大三开学在即,希望现在来学java还来得及。

本文出自于博客园兰幽,转载请说明出处。

java线程一之创建线程、线程池以及多线程运行时间统计的更多相关文章

  1. JVM源码分析之一个Java进程究竟能创建多少线程

    JVM源码分析之一个Java进程究竟能创建多少线程 原创: 寒泉子 你假笨 2016-12-06 概述 虽然这篇文章的标题打着JVM源码分析的旗号,不过本文不仅仅从JVM源码角度来分析,更多的来自于L ...

  2. Linux 进程与线程一(创建-关闭线程)

    进程是一个实体.每一个进程都有他自己的内存地址段(heap,stack等等) 进程是执行中的程序. 程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体. 进程是操作系统中最基 ...

  3. Java并发编程(十一)线程池的使用

    1.new Thread的弊端如下: a. 每次new Thread新建对象性能差. b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom. c. 缺乏更多 ...

  4. 和朱晔一起复习Java并发(一):线程池

    和我之前的Spring系列文章一样,我们会以做一些Demo做实验的方式来复习一些知识点. 本文我们先从Java并发中最最常用的线程池开始. 从一个线程池实验开始 首先我们写一个方法来每秒一次定时输出线 ...

  5. java并发编程(四) 线程池 & 任务执行、终止源码分析

    参考文档 线程池任务执行全过程:https://blog.csdn.net/wojiaolinaaa/article/details/51345789 线程池中断:https://www.cnblog ...

  6. Java并发编程与技术内幕:线程池深入理解

    摘要: 本文主要讲了Java当中的线程池的使用方法.注意事项及其实现源码实现原理,并辅以实例加以说明,对加深Java线程池的理解有很大的帮助. 首先,讲讲什么是线程池?照笔者的简单理解,其实就是一组线 ...

  7. Android线程管理之ThreadPoolExecutor自定义线程池

    前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己 ...

  8. java如何停止一个运行的线程?

    关于线程的一点心得 //首先导入需要的包 improt java.util.Timer;import java.io.File;import java.util.TimerTask; //首先需要创建 ...

  9. Java知多少(58)线程Runnable接口和Thread类详解

    大多数情况,通过实例化一个Thread对象来创建一个线程.Java定义了两种方式: 实现Runnable 接口: 可以继承Thread类. 下面的两小节依次介绍了每一种方式. 实现Runnable接口 ...

随机推荐

  1. RAID磁盘阵列的原理

    RAID概念 磁盘阵列(Redundant Arrays of Independent Disks,RAID),有“独立磁盘构成的具有冗余能力的阵列”之意.磁盘阵列是由很多价格较便宜的磁盘,以硬件(R ...

  2. [异常笔记]启动DFS报错:Cannot find configuration directory: /etc/hadoop

    [hadoop@master ~]$ start-dfs.sh Incorrect configuration: namenode address dfs.namenode.servicerpc-ad ...

  3. jquery头像上传剪裁插件cropper的前后台demo

    因为一个项目要做一个头像上传的功能,因此选择了使用jquery的头像插件cropper,cropper是一款使用简单且功能强大的图片剪裁jQuery插件,但是在使用的时候,有一个很大的坑需要注意,那就 ...

  4. mysql的docker化安装

    mysql版本有很多,先看下各类版本号说明: 3.X至5.1.X:这是早期MySQL的版本.常见早期的版本有:4.1.7.5.0.56等. 5.4.X到5.7.X:这是为了整合MySQL AB公司社区 ...

  5. PHP运行原理之Opcodes

    在我之前的博客<Laravel5框架性能优化技巧>中提到开启OPcache可以提升php性能.那么为什么开启OPcache就可以提升php运行性能呢?这里就要提到php的运行原理了--Op ...

  6. vmware 虚拟机设置 redhat 桥接模式

    1.设置 vmware 网络模式 2.设置 linux 网络模式

  7. 异 形 卵 南阳acm709

    异 形 卵 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 我们探索宇宙,是想了解浩瀚星空的奥妙,但我们却很少意识到宇宙深处藏匿的危险,它们无时无刻不紧盯着我们的地球 ...

  8. axios请求封装和异常统一处理

    前端网络请求封装前端采用了axios来处理网络请求,为了避免在每次请求时都去判断各种各样的网络情况,比如连接超时.服务器内部错误.权限不足等等不一而足,我对axios进行了简单的封装,这里主要使用了a ...

  9. IDEA阿里Java规范插件的安装

    本文参考自阿飞博客:http://www.cnblogs.com/aflyun/p/7668306.html 官方使用教程:https://zhuanlan.zhihu.com/p/30191998? ...

  10. mfc通过MapWinGIS控件读取shp文件(通过#import实现)

    在MFC工程中想使用MapWinGIS组件,有多种方法可以实现, 第一种方法,#Import来实现 1.首先注册MapWinGIS ActiveX组件, 2.新建一个单文档工程:MapGis,为控件添 ...