一、线程的概要绍
从员工搬货看多线程
现在有一大推货物堆着,如果我有5个员工搬,肯定会比一个员工搬要快速。但是若是有15个员工搬同一堆货物,中间肯定会因为空间以及货物争抢而产生摩擦,甚至会互相掐架。所以,这就不意味着线程越多越好,合理的使用多线程,可以充分提升处理器的利用率,提高工作效率

线程与进程
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。
线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
多进程是指操作系统能同时运行多个任务(程序)。
多线程是指在同一程序中有多个顺序流在执行。
所以线程被包含在进程里,两者范畴不一样

多线程使用的目的:
1、 吞吐量:做WEB,容器帮你做了多线程,但是它只能帮你做请求层面的,简单的说,就是一个请求一个线程(如struts2,是多线程的,每个客户端请求创建一个实例,保证线程安全),或多个请求一个线程,如果是单线程,那只能是处理一个用户的请求
2、 伸缩性:通过增加CPU核数来提升性能。
多线程的使用场景:
1、 常见的B/S服务(浏览器、Web服务)web处理请求(一般web中间件会自动管理线程),各种专用服务器(如游戏服务器)
2、 FTP下载,多线程操作文件
3、 数据库用到的多线程
4、 分布式计算
5、 tomcat内部采用多线程,上百个客户端访问同一个WEB应用,tomcat接入后就是把后续的处理扔给一个新的线程来处理,这个新的线程最后调用我们的servlet程序,比如doGet或者dpPost方法
6、 后台任务:如定时向大量(100W以上)的用户发送邮件;定期更新配置文件、任务调度(如quartz),一些监控用于定期信息采集
7、 异步处理:如发微博、记录日志
8、费时应用开发,一个费时的计算开个线程,前台加个进度条显示
9、swing编程

二、多线程的实现式
常用的实现多线程的方有三种,分别是继承Thread类、实现Runnable接口和使用ExecutorService、Callable、Future实现带有返回结果的多线程。下面一一举例说明。

继承Thread类实现多线程
继承Thread类的方法尽管被视为一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,但是线程在调用start()方法之后并不是立马就执行,而是将线程处于可执行状态,什么时候执行是由操作系统决定的,在执行期间线程将会执行run()方法里的内容。

package com.test.thread;import java.util.HashMap;
import java.util.Map;public class ThreadDemo extends Thread {private String name;public ThreadDemo(String name){this.name = name;}@Overridepublic void run() {Map<String, String> map = new HashMap<>();for (int i = 1; i <= 5; i++) {map.put("name"+i, name);    //将name+1作为key值,value为传入的线程名字                           }this.getInfo(map);  //调用map的打印方法}public void getInfo(Map<String, String> map){for (String str : map.keySet()) {           System.out.println("名为 "+Thread.currentThread().getName()+" value= "+map.get(str));}}public static void main(String[] args) {Thread t1 = new ThreadDemo("别闹");   //定义一个新线程t1.start();     //启动线程。注意,线程在启动之后并不一定是立马执行,什么时候执行取决于操作系统Thread t2 = new ThreadDemo("别闹+1");t2.start();Thread t3 = new ThreadDemo("别闹+2");t3.start();}
}

输出:
名为 Thread-1 value= 别闹+1
名为 Thread-0 value= 别闹
名为 Thread-2 value= 别闹+2
名为 Thread-0 value= 别闹
名为 Thread-1 value= 别闹+1
名为 Thread-0 value= 别闹
名为 Thread-2 value= 别闹+2
名为 Thread-0 value= 别闹
名为 Thread-1 value= 别闹+1
名为 Thread-0 value= 别闹
名为 Thread-2 value= 别闹+2
名为 Thread-1 value= 别闹+1
名为 Thread-2 value= 别闹+2
名为 Thread-1 value= 别闹+1
名为 Thread-2 value= 别闹+2

再运行一下:

名为 Thread-0 value= 别闹
名为 Thread-1 value= 别闹+1
名为 Thread-2 value= 别闹+2
名为 Thread-2 value= 别闹+2
名为 Thread-2 value= 别闹+2
名为 Thread-2 value= 别闹+2
名为 Thread-2 value= 别闹+2
名为 Thread-0 value= 别闹
名为 Thread-0 value= 别闹
名为 Thread-0 value= 别闹
名为 Thread-0 value= 别闹
名为 Thread-1 value= 别闹+1
名为 Thread-1 value= 别闹+1
名为 Thread-1 value= 别闹+1
名为 Thread-1 value= 别闹+1

说明:
程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建。随着调用ThreadDemo 的3个对象的start方法,另外3个线程也启动了,这样,整个应用就在多线程下运行。
由上面的执行结果看出,线程的名字若没有自定义,则会使用默认的名字,格式为“Thread-第几个线程”。线程的执行顺序是随机的,一般正常情况下都是线程间交叉执行。

实现Runnable接口方式实现多线程
我们都知道,一个子类只能继承一个父类,如果一个类继承了一个父类,那就不能通过继承Thread父类来实现多线程了,这时,就可以通过实现Runnable接口,来实现多线程。

package com.test.thread;import java.util.HashMap;
import java.util.Map;public class ThreadDemo implements Runnable {private String name;public ThreadDemo(String name){this.name = name;}@Overridepublic void run() {Map<String, String> map = new HashMap<>();for (int i = 1; i <= 5; i++) {map.put("name"+i, name);    //将name+1作为key值,value为传入的线程名字                           }this.getInfo(map);  //调用map的打印方法}public void getInfo(Map<String, String> map){for (String str : map.keySet()) {           System.out.println("名为 "+Thread.currentThread().getName()+" 打印的key= "+str+" value= "+map.get(str));}}public static void main(String[] args) {Runnable runnable = new ThreadDemo("无厘头");Thread t1 = new Thread(runnable, "线程1");t1.start();Thread t2 = new Thread(runnable,"线程2");t2.start();Thread t3 = new Thread(runnable,"线程3");t3.start();}
}

输出:
名为 线程3 打印的key= name5 value= 无厘头
名为 线程1 打印的key= name5 value= 无厘头
名为 线程1 打印的key= name3 value= 无厘头
名为 线程1 打印的key= name4 value= 无厘头
名为 线程1 打印的key= name1 value= 无厘头
名为 线程1 打印的key= name2 value= 无厘头
名为 线程2 打印的key= name5 value= 无厘头
名为 线程2 打印的key= name3 value= 无厘头
名为 线程2 打印的key= name4 value= 无厘头
名为 线程3 打印的key= name3 value= 无厘头
名为 线程2 打印的key= name1 value= 无厘头
名为 线程2 打印的key= name2 value= 无厘头
名为 线程3 打印的key= name4 value= 无厘头
名为 线程3 打印的key= name1 value= 无厘头
名为 线程3 打印的key= name2 value= 无厘头

说明:
ThreadDemo类通过实现Runnable接口,使得该类有了多线程类的特征。run()方法是多线程程序的一个约定。所有的多线程代码都在run方法里面。在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target, String name) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。

使用ExecutorService、Callable、Future实现带有返回结果的多线程
上面所讲述的两种实现多线程的方法,都是没有返回值的,如果想要实现带返回值的多线程,不妨试一下,下面这种方法。

@SuppressWarnings("unchecked")
public class Test {
public static void main(String[] args) throws ExecutionException,  InterruptedException {  System.out.println("----程序开始运行----");  Date date1 = new Date();  int taskSize = 5;  // 创建一个线程池  ExecutorService pool = Executors.newFixedThreadPool(taskSize);  // 创建多个有返回值的任务  List<Future> list = new ArrayList<Future>();  for (int i = 0; i < taskSize; i++) {  Callable c = new MyCallable(i + " ");  // 执行任务并获取Future对象  Future f = pool.submit(c);  // System.out.println(">>>" + f.get().toString());  list.add(f);  }  // 关闭线程池  pool.shutdown();  // 获取所有并发任务的运行结果  for (Future f : list) {  // 从Future对象上获取任务的返回值,并输出到控制台  System.out.println(">>>" + f.get().toString());  }  Date date2 = new Date();  System.out.println("----程序结束运行----,程序运行时间【"  + (date2.getTime() - date1.getTime()) + "毫秒】");
}
}  class MyCallable implements Callable<Object> {
private String taskNum;  MyCallable(String taskNum) {  this.taskNum = taskNum;
}  public Object call() throws Exception {  System.out.println(">>>" + taskNum + "任务启动");  Date dateTmp1 = new Date();  Thread.sleep(1000);  Date dateTmp2 = new Date();  long time = dateTmp2.getTime() - dateTmp1.getTime();  System.out.println(">>>" + taskNum + "任务终止");  return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";
}  

输出:

说明:
可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现传说中有返回结果的多线程了。
ExecutorService、Callable、Future这些对象实际上都是属于Executor框架中的功能类,推荐大家去看看Executor框架。

多线程的应用场景以及其实现方式相关推荐

  1. 多进程和多线程的使用场景

    多进程和多线程的使用场景 多进程模型的优势是CPU,多线程模型的优势是线程间切换代价较小 多线程模型适用于I/O密集型的工作场景,因此I/O密集型的工作场景经常会由于I/O阻塞导致频繁的切换线程.同时 ...

  2. Python多进程和多线程的使用场景

    Python多进程适用的场景:计算密集型(CPU密集型)任务 Python多线程适用的场景:IO密集型任务 计算密集型任务一般指需要做大量的逻辑运算,比如上亿次的加减乘除,使用多核CPU可以并发提高计 ...

  3. Python多线程多进程应用场景

    IO密集型: 推荐使用多线程 CPU密集型: 推荐使用多进程 为什么Python多线程在CPU密集型中是鸡肋?通过一段代码来测试 单线程执行从1亿递减到0 import datetimedef run ...

  4. Java多线程的应用场景和应用目的举例

    微信公众号:javafirst 01 通俗的解释一下多线程 多线程用于堆积处理,就像一个大土堆,一个推土机很慢,那么10个推土机一起来处理,当然速度就快了,不过由于位置的限制,如果20个推土机,那么推 ...

  5. Java多线程:多线程同步安全问题的 “三“ 种处理方式 ||多线程 ”死锁“ 的避免 || 单例模式”懒汉式“的线程同步安全问题

    Java多线程:多线程同步安全问题的 "三" 种处理方式 ||多线程 "死锁" 的避免 || 单例模式"懒汉式"的线程同步安全问题 每博一文 ...

  6. Java 并发 多线程:创建线程的四种方式

    Java 并发 多线程: 创建线程的四种方式 继承 Thread 类并重写 run 方法 实现 Runnable 接口 实现 Callable 接口 使用线程池的方式创建 1. 通过继承 Thread ...

  7. python适用场景_你真的了解Python吗?什么场景使用多线程,什么场景使用多进程?...

    引言 涉及并发的场景,大家想到使用多线程或多进程解决并发问题; 一般情况下,解决多并发场景问题,多数语言采用多线程编程模式(线程是轻量级的进程,共用一份进程空间). 也同样适用于Python多并发处理 ...

  8. 多线程相关实例(多线程经典应用场景)

    转载,from 网络,未能找到原创人员,只找到一个转载 https://blog.csdn.net/u013521220/article/details/79648270 多线程实例目录 相关知识: ...

  9. java多线程使用业务场景_Java多线程使用场景

    一.几个基本概念的区分 1.进程与程序的区分 程序 进程 包含代码部分.数据部分 包含代码部分.数据部分.进程控制块 顺序执行 并发执行 独占资源 共享资源 同步的 异步的 静态的 动态的 (本质区别 ...

最新文章

  1. 【Java】 Base64原理及简单应用
  2. Web开发框架 SSH 简介
  3. java 参数命名冲突_Java中的命名参数
  4. oracle入库的速度能到多少_多线程能提高Oracle的入库速度吗
  5. [POI2009]Wie
  6. R中因子分析的得分计算
  7. BERT-BiLSTM-CRF命名实体识别应用
  8. Atitit.redis操作总结
  9. python身份证号码计算年龄
  10. 常见算法的英文命名(排序、查找)
  11. MATLAB代码:面向削峰填谷的电动汽车多目标优化调度策略
  12. Pyecharts绘制图表大全——柱形图
  13. 路由器密码重置(更改寄存器的值)
  14. 一些牛逼哄哄的javascript面试题
  15. TestNG跳过某个测试方法
  16. 如何快速制作gif图片
  17. 京东到家开放平台消息系统-进阶之路
  18. Kafka:High level consumer vs. Low level consumer
  19. 【转】Python之获取每日涨停板股票数据并绘制K线图!
  20. json数据和本地存储

热门文章

  1. Android腾讯微博分享
  2. 使用JavaMail实现收取和回复邮件
  3. 云原生之容器编排实践-在CentOS7上安装minikube
  4. DVD-RW与DVD-ROM的区别
  5. 幻影追逐者服务器维护,《幻影追逐者》游戏特色曝光 开启与邪恶争斗冒险之旅...
  6. STL源码剖析之配接器
  7. 求购运用于苹果操作系统的电子白板软件!!急!!
  8. Error: EPERM: operation not permitted, mkdir......
  9. 颈椎神经分布立体图高清,颈椎神经分布立体图片
  10. java web ppt_javawebppt演讲