Java基础之多线程框架
一.进程与线程的区别
1.定义:
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
2.关系:
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。
相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
3.区别:
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
3.1线程的划分尺度小于进程,使得多线程程序的并发性高。
3.2简而言之,一个程序至少有一个进程,一个进程至少有一个线程。
3.3另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
3.4线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
3.5从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
4.优缺点:
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
二.多线程两个基本实现框架
Java编写程序都运行在在Java虚拟机(JVM)中,在JVM的内部,程序的多任务是通过线程来实现的。每用Java命令启动一个Java应用程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个JVM环境中,所有程序代码的运行都是以线程来运行。
在Java中,多线程的实现有两种基本方式:继承java.lang.Thread类;实现java.lang.Runnable接口。(优先选择)。
第三种方式(少):使用ExecutorService、Callable、Future实现有返回结果的多线程。
1.继承Thread类来实现多线程
当一个类继承Thread类时,在类中必须重载run()方法,同时这个run()方法也是线程的入口,在调用的过程中,通过调用start()方法来启动新线程,其基本框架为:
class 类名 extends Thread{
方法1;
方法2;
…public void run(){ // other code… } 属性1; 属性2; … }
一般生活场窗口售票情况:
1 class TestThread extends Thread 2 { 3 private String name; 4 public TestThread(String name) 5 { 6 this.name=name; 7 } 8 public void run() 9 { 10 11 for (int i = 0; i < 7; i++) 12 { 13 if (num > 0) 14 { 15 System.out.println(name+"正在卖票 "+"num= " + num--); 16 } 17 } 18 } 19 20 public static void main(String[] args) 21 { 22 23 TestThread h1 = new TestThread("窗口1"); 24 TestThread h2 = new TestThread("窗口2"); 25 TestThread h3 = new TestThread("窗口3"); 26 h1.start(); 27 h2.start(); 28 h3.start(); 29 } 30 private int num = 4; 31 }
这样出现的问题是:1.不清楚线程之间执行的具体顺序,2.相当于每个窗口都在售卖4张票。
优化方案:实现Runnable接口
2.实现Runnable接口来实现多线程
和继承Thread类似,当一个类实现Runnable接口时,在类中也必须重载run()方法,同时这个run()方法也是线程的入口,在调用的过程中,通过调用start()方法来启动新线程,其基本框架为:
class 类名 implements Runnable{方法1;方法2;…public void run(){ // other code… } 属性1; 属性2; … }
代码改进:
class MyThread implements Runnable { private int ticket = 5; //5张票public void run() {for (int i=0; i<=20; i++) {if (this.ticket > 0) {System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);}}}}public class TestThread { public static void main(String [] args) {MyThread my = new MyThread();new Thread(my, "1号窗口").start();new Thread(my, "2号窗口").start();new Thread(my, "3号窗口").start();}}
程序执行的结果为:
1 1号窗口正在卖票5 2 1号窗口正在卖票4 3 1号窗口正在卖票3 4 2号窗口正在卖票2 5 1号窗口正在卖票1
3.使用ExecutorService、Callable、Future实现有返回结果的多线程
ExecutorService、Callable、Future这个对象实际上都是属于Executor框架中的功能类。返回结果的线程是在JDK1.5中引入的新特征,确实很实用,有了这种特征我就不需要再为了得到返回值而大费周折了,而且即便实现了也可能漏洞百出。可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。
1 import java.util.concurrent.*; 2 import java.util.Date; 3 import java.util.List; 4 import java.util.ArrayList; 5 6 /** 7 * 有返回值的线程 8 */ 9 @SuppressWarnings("unchecked") 10 public class Test { 11 public static void main(String[] args) throws ExecutionException, 12 InterruptedException { 13 System.out.println("----程序开始运行----"); 14 Date date1 = new Date(); 15 16 int taskSize = 5; 17 // 创建一个线程池 18 ExecutorService pool = Executors.newFixedThreadPool(taskSize); 19 // 创建多个有返回值的任务 20 List<Future> list = new ArrayList<Future>(); 21 for (int i = 0; i < taskSize; i++) { 22 Callable c = new MyCallable(i + " "); 23 // 执行任务并获取Future对象 24 Future f = pool.submit(c); 25 // System.out.println(">>>" + f.get().toString()); 26 list.add(f); 27 } 28 // 关闭线程池 29 pool.shutdown(); 30 31 // 获取所有并发任务的运行结果 32 for (Future f : list) { 33 // 从Future对象上获取任务的返回值,并输出到控制台 34 System.out.println(">>>" + f.get().toString()); 35 } 36 37 Date date2 = new Date(); 38 System.out.println("----程序结束运行----,程序运行时间【" 39 + (date2.getTime() - date1.getTime()) + "毫秒】"); 40 } 41 } 42 43 class MyCallable implements Callable<Object> { 44 private String taskNum; 45 46 MyCallable(String taskNum) { 47 this.taskNum = taskNum; 48 } 49 50 public Object call() throws Exception { 51 System.out.println(">>>" + taskNum + "任务启动"); 52 Date dateTmp1 = new Date(); 53 Thread.sleep(1000); 54 Date dateTmp2 = new Date(); 55 long time = dateTmp2.getTime() - dateTmp1.getTime(); 56 System.out.println(">>>" + taskNum + "任务终止"); 57 return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】"; 58 } 59 }
代码说明:
上述代码中Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。
二:补充说明
在继承Thread类实现多线程时,我们创建了三个不同的对象,所以创建的三个线程实际上是完成的三个不同的任务,所以才会相互独立的完成;而通过实现Runable接口来实现多线程时,我们只创建了一个对象,然后实例化三个不同的线程去完成这个任务,所以相当于是共同完成任务。
Thread类也是实现Runnable接口的:
class Thread implements Runnable {//…public void run() {if (target != null) { target.run(); } } }
Thread中的run方法其实就是调用的是Runnable接口的run方法。
Reference:http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html
转载于:https://www.cnblogs.com/wangzhengyu/p/8527308.html
Java基础之多线程框架相关推荐
- Java基础、多线程、JVM、集合八股文自述(持续更新)
Java基础.多线程.JVM.集合八股文自述 一.Java基础 1.1 object类有哪些方法? getClass().hashCode().equals().clone().toString(). ...
- Thinking in java基础之集合框架
Thinking in java基础之集合框架 大家都知道我的习惯,先上图说话. 集合简介(容器) 把具有相同性质的一类东西,汇聚成一个整体,就可以称为集合,例如这里有20个苹果,我们把每一个苹果当成 ...
- java把map值放入vector_Thinking in java基础之集合框架
Thinking in java基础之集合框架 大家都知道我的习惯,先上图说话. 集合简介(容器) 把具有相同性质的一类东西,汇聚成一个整体,就可以称为集合,例如这里有20个苹果,我们把每一个苹果当成 ...
- JAVA基础+集合+多线程+JVM
1. Java 基础 1.1. 面向对象和面向过程的区别 面向过程性能比面向对象高. 因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候 等一般采用面向过程开发.但是 ...
- java基础学习-多线程笔记
说说Java中实现多线程有几种方法 创建线程的常用三种方式: 1. 继承Thread类 2. 实现Runnable接口 3. 实现Callable接口( JDK1.5>= ) 4. 线程池方式创 ...
- Java基础之多线程详细分析
在了解多线程之前,先来了解一下进程与线程之间的关系. 进程和线程: 进程是指在系统中正在执行的一个程序,每个进程之间是独立的. 线程是进程的一个基本执行单元.一个进程要想执行任务,必须得有线程(每1个 ...
- Java基础21 多线程线程两种实现方式 锁
一.多线程的概念 1.程序 :一个固定逻辑与数据的集合 就称为程序 例如淘宝 贪吃蛇小游戏 2.CPU: 中央处理器 主要用于协调程序与硬件进行配置的工作 3.并发与并行 1.并发(高并发) 在同一个 ...
- Java基础系列--Executor框架(一)
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/8393618.html 一.Executor框架介绍 Executor框架是JDK1.5之后 ...
- 【Java基础】多线程
线程及与进程的区别 线程也被称为是轻量级的进程,是程序执行的最小单元.有四种状态:运行,就绪,挂起和结束.一个进程拥有多个线程,这些线程共享进程的一些资源如打开的文件,代码段,数据段和堆空间. 使用线 ...
最新文章
- 用于时序动作提名生成任务,爱奇艺提出BC-GNN图神经网络 | ECCV 2020
- HDU4857拓扑排序模版题
- Django - 分页器
- 7.2 matlab符号微积分(符号函数的极限、导数和积分)
- 五款主流 Linux 发行版性能对比,稳而不强?
- DevExpress的TextEdit控件没法调整高度解决
- 计算机会考咋查成绩,2019会考成绩查询网址入口 高中会考怎么查成绩
- 进程、线程、信号量和互斥锁
- HTML把表格链接进下拉菜单,excel表格下拉菜单怎么做
- 关于C#中的DLLImport
- 两端“弱智”的HTML代码
- c语言课件谭浩强ppt下载,c语言课件谭浩强
- 常见视频接口知识点汇总(精华)
- 给各位“老划水员”分享10款提高幸福指数的VSCode“摸鱼神器“
- windows安装Pentaho Server
- 阿里靠什么武功秘籍渡过“双十一“的天量冲击
- Win2008:在 Win2008R2 中安装 PowerShell 4.0 (旧作)
- 银河麒麟系统QtCreator不能切换中文输入法问题解决
- 短信系统实现原理(基于redis)
- Ubuntu 16.04 鼠标可以移动不能点击问题
热门文章
- mysql隐式锁定辅助索引_当Mysql - InnoDB行锁遇到复合主键和多列索引-Go语言中文社区...
- prometheus的搭建与使用
- 如何提高lstm的预测精度_如何提高示波器的测试精度?五大因素助您了解!
- Linux之后台运行(nohup和)
- java 错误日期转正确日期_Java日期格式转换-错误的月份
- python 网站 源码_在线浏览美图源码,附带python源码
- 高精度算法(加减乘除取模(均可以处理负数))
- java模拟器apk闪退_急,求帮助,eclipse生成apk安装以后闪退
- spring扫描自定义注解并进行操作
- Geoserver怎样设置地图shp文件为相对路径,可轻松复制移植