今日内容介绍
1、多线程
2、线程池

01进程概念

A:进程概念

a:进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,

即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。

02线程的概念

A:线程的概念

a:线程:线程是进程中的一个执行单元(执行路径),负责当前进程中程序的执行,

一个进程中至少有一个线程。一个进程中是可以有多个线程的,

这个应用程序也可以称之为多线程程序。

  1. 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程

03深入线程的概念

A:深入线程的概念

什么是多线程呢?

即就是一个程序中有多个线程在同时执行。

一个核心的CPU在多个线程之间进行着随即切换动作,由于切换时间很短(毫秒甚至是纳秒级别),导致我们感觉不出来

单线程程序:即,若有多个任务只能依次执行。当上一个任务执行结束后,下一个任务开始执行。如去 网吧上网,网吧只能让一个人上网,当这个人下机后,下一个人才能上网。

多线程程序:

即,若有多个任务可以同时执行。如,去网吧上网,网吧能够让多个人同时上网。

04迅雷的多线程下载

A:迅雷的多线程下载

多线程,每个线程都读一个文件

05线程的运行模式

A:线程的运行模式

a:分时调度

所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

b:抢占式调度

优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),
Java使用的为抢占式调度。

大部分操作系统都支持多进程并发运行,现在的操作系统几乎都支持同时运行多个程序。比如:
现在我们上课一边使用编辑器,一边使用录屏软件,同时还开着画图板,dos窗口等软件。
此时,这些程序是在同时运行,”感觉这些软件好像在同一时刻运行着“。

实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。
对于CPU的一个核而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度
相对我们的感觉要快,看上去就是在同一时刻运行。
其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。

06main的主线程

A:main的主线程

  1. /*
  2. * 程序中的主线程
  3. */
  4. public class Demo {
  5. public static void main(String[] args) {
  6. System.out.println(0/0);
  7. function();
  8. System.out.println(Math.abs(-9));
  9. }
  10. public static void function(){
  11. for(int i = 0 ; i < 10000;i++){
  12. System.out.println(i);
  13. }
  14. }
  15. }

07Thread类介绍

A:Thread类介绍:

Thread是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。

发现创建新执行线程有两种方法

a:一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。创建对象,开启线程。run方法相当于其他线程的main方法。

b:另一种方法是声明一个实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程。

08实现线程程序继承Thread

*A:实现线程程序继承Thread

  1. /*
  2. * 创建和启动一个线程
  3. * 创建Thread子类对象
  4. * 子类对象调用方法start()
  5. * 让线程程序执行,JVM调用线程中的run
  6. */
  7. public class ThreadDemo {
  8. public static void main(String[] args) {
  9. SubThread st = new SubThread();
  10. SubThread st1 = new SubThread();
  11. st.start();
  12. st1.start();
  13. for(int i = 0; i < 50;i++){
  14. System.out.println("main..."+i);
  15. }
  16. }
  17. }
  18. /*
  19. * 定义子类,继承Thread
  20. * 重写方法run
  21. */
  22. public class SubThread extends Thread{
  23. public void run(){
  24. for(int i = 0; i < 50;i++){
  25. System.out.println("run..."+i);
  26. }
  27. }
  28. }

09线程执行的随机性

A:线程执行的随机性

  1. /*
  2. 代码分析:
  3. 整个程序就只有三个线程,
  4. 一个是主线程
  5. 启动另外两个线程
  6. st.start();
  7. st1.start();
  8. for(int i = 0; i < 50;i++){
  9. System.out.println("main..."+i);
  10. }
  11. 一个是st(Thread-0)线程
  12. for(int i = 0; i < 50;i++){
  13. System.out.println("run..."+i);
  14. }
  15. 一个是st1(Thread-1)线程下
  16. */
  17. public class ThreadDemo {
  18. public static void main(String[] args) {
  19. SubThread st = new SubThread();
  20. SubThread st1 = new SubThread();
  21. st.start();
  22. st1.start();
  23. for(int i = 0; i < 50;i++){
  24. System.out.println("main..."+i);
  25. }
  26. }
  27. }
  28. /*
  29. * 定义子类,继承Thread
  30. * 重写方法run
  31. */
  32. public class SubThread extends Thread{
  33. public void run(){
  34. for(int i = 0; i < 50;i++){
  35. System.out.println("run..."+i);
  36. }
  37. }
  38. }

10为什么要继承Thread

A:什么要继承Thread

  1. a:我们为什么要继承Thread类,并调用其的start方法才能开启线程呢?
  2. 继承Thread类:因为Thread类用来描述线程,具备线程应该有功能。那为什么不直接创建Thread类的对象呢?
  3. 如下代码:
  4. Thread t1 = new Thread();
  5. t1.start();//这样做没有错,但是该start调用的是Thread类中的run方法
  6. //而这个run方法没有做什么事情,更重要的是这个run方法中并没有定义我们需要让线程执行的代码。
  7. b:创建线程的目的是什么?
  8. 是为了建立程序单独的执行路径,让多部分代码实现同时执行。也就是说线程创建并执行需要给定线程要执行的任务。
  9. 对于之前所讲的主线程,它的任务定义在main函数中。自定义线程需要执行的任务都定义在run方法中。

11多线程内存图解

A:多线程内存图解

  1. 多线程执行时,到底在内存中是如何运行的呢?
  2. 多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈。
  3. 当执行线程的任务结束了,线程自动在栈内存中释放了。但是当所有的执行线程都结束了,那么进程就结束了。

12获取线程名字Thread类方法getName

A:获取线程名字Thread类方法getName

  1. /*
  2. * 获取线程名字,父类Thread方法
  3. * String getName()
  4. */
  5. public class NameThread extends Thread{
  6. public NameThread(){
  7. super("小强");
  8. }
  9. public void run(){
  10. System.out.println(getName());
  11. }
  12. }
  13. /*
  14. * 每个线程,都有自己的名字
  15. * 运行方法main线程,名字就是"main"
  16. * 其他新键的线程也有名字,默认 "Thread-0","Thread-1"
  17. *
  18. * JVM开启主线程,运行方法main,主线程也是线程,是线程必然就是
  19. * Thread类对象
  20. */
  21. public class ThreadDemo {
  22. public static void main(String[] args) {
  23. NameThread nt = new NameThread();
  24. nt.start();
  25. }
  26. }

13获取线程名字Thread类方法currentThread

A:获取线程名字Thread类方法currentThread

  1. /*
  2. * 获取线程名字,父类Thread方法
  3. * String getName()
  4. */
  5. public class NameThread extends Thread{
  6. public void run(){
  7. System.out.println(getName());
  8. }
  9. }
  10. /*
  11. * 每个线程,都有自己的名字
  12. * 运行方法main线程,名字就是"main"
  13. * 其他新键的线程也有名字,默认 "Thread-0","Thread-1"
  14. *
  15. * JVM开启主线程,运行方法main,主线程也是线程,是线程必然就是
  16. * Thread类对象
  17. * Thread类中,静态方法
  18. * static Thread currentThread()返回正在执行的线程对象
  19. */
  20. public class ThreadDemo {
  21. public static void main(String[] args) {
  22. NameThread nt = new NameThread();
  23. nt.start();
  24. /*Thread t =Thread.currentThread();
  25. System.out.println(t.getName());*/
  26. System.out.println(Thread.currentThread().getName());
  27. }
  28. }

14线程名字设置

A:线程名字设置

  1. /*
  2. * 获取线程名字,父类Thread方法
  3. * String getName()
  4. */
  5. public class NameThread extends Thread{
  6. public NameThread(){
  7. super("小强");
  8. }
  9. public void run(){
  10. System.out.println(getName());
  11. }
  12. }
  13. /*
  14. * 每个线程,都有自己的名字
  15. * 运行方法main线程,名字就是"main"
  16. * 其他新键的线程也有名字,默认 "Thread-0","Thread-1"
  17. *
  18. * JVM开启主线程,运行方法main,主线程也是线程,是线程必然就是
  19. * Thread类对象
  20. * Thread类中,静态方法
  21. * static Thread currentThread()返回正在执行的线程对象
  22. */
  23. public class ThreadDemo {
  24. public static void main(String[] args) {
  25. NameThread nt = new NameThread();
  26. nt.setName("旺财");
  27. nt.start();
  28. }
  29. }

15Thread类方法sleep

A:Thread类方法sleep

  1. public class ThreadDemo {
  2. public static void main(String[] args) throws Exception{
  3. /*for(int i = 0 ; i < 5 ;i++){
  4. Thread.sleep(50);
  5. System.out.println(i);
  6. }*/
  7. new SleepThread().start();
  8. }
  9. }
  10. public class SleepThread extends Thread{
  11. public void run(){
  12. for(int i = 0 ; i < 5 ;i++){
  13. try{
  14. Thread.sleep(500);//睡眠500ms,500ms已到并且cpu切换到该线程继续向下执行
  15. }catch(Exception ex){
  16. }
  17. System.out.println(i);
  18. }
  19. }
  20. }

16实现线程的另一种方式实现Runnable接口

A:实现线程的另一种方式实现Runnable接口

  1. /*
  2. * 实现接口方式的线程
  3. * 创建Thread类对象,构造方法中,传递Runnable接口实现类
  4. * 调用Thread类方法start()
  5. */
  6. public class ThreadDemo {
  7. public static void main(String[] args) {
  8. SubRunnable sr = new SubRunnable();
  9. Thread t = new Thread(sr);
  10. t.start();
  11. for(int i = 0 ; i < 50; i++){
  12. System.out.println("main..."+i);
  13. }
  14. }
  15. }
  16. /*
  17. * 实现线程成功的另一个方式,接口实现
  18. * 实现接口Runnable,重写run方法
  19. */
  20. public class SubRunnable implements Runnable{
  21. public void run(){
  22. for(int i = 0 ; i < 50; i++){
  23. System.out.println("run..."+i);
  24. }
  25. }
  26. }

17实现接口方式的好处

A:实现接口方式的好处

  1. 第二种方式实现Runnable接口避免了单继承的局限性,所以较为常用。
  2. 实现Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。
  3. 继承Thread类,线程对象和线程任务耦合在一起。
  4. 一旦创建Thread类的子类对象,既是线程对象,有又有线程任务。
  5. 实现runnable接口,将线程任务单独分离出来封装成对象,类型就是Runnable接口类型。Runnable接口对线程对象和线程任务进行解耦。
  6. (降低紧密性或者依赖性,创建线程和执行任务不绑定)

18匿名内部类实现线程程序

A:匿名内部类实现线程程序

  1. /*
  2. * 使用匿名内部类,实现多线程程序
  3. * 前提: 继承或者接口实现
  4. * new 父类或者接口(){
  5. * 重写抽象方法
  6. * }
  7. */
  8. public class ThreadDemo {
  9. public static void main(String[] args) {
  10. //继承方式 XXX extends Thread{ public void run(){}}
  11. new Thread(){
  12. public void run(){
  13. System.out.println("!!!");
  14. }
  15. }.start();
  16. //实现接口方式 XXX implements Runnable{ public void run(){}}
  17. Runnable r = new Runnable(){
  18. public void run(){
  19. System.out.println("###");
  20. }
  21. };
  22. new Thread(r).start();
  23. new Thread(new Runnable(){
  24. public void run(){
  25. System.out.println("@@@");
  26. }
  27. }).start();
  28. }
  29. }

19线程的状态图

A:线程的状态图

20线程池的原理

A:线程池的原理

  1. 1.java中,如果每个请求到达就创建一个新线程,开销是相当大的。
  2. 2.在实际使用中,创建和销毁线程花费的时间和消耗的系统资源都相当大
  3. ,甚至可能要比在处理实际的用户请求的时间和资源要多的多。
  4. 3.除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。
  5. 如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资
  6. 源不足。
  7. 为了防止资源不足,需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创
  8. 建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务。
  9. 线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程
  10. ,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在
  11. ,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另
  12. 外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。

21JDK5实现线程池

A:JDK5实现线程池

  1. /*
  2. * JDK1.5新特性,实现线程池程序
  3. * 使用工厂类 Executors中的静态方法创建线程对象,指定线程的个数
  4. * static ExecutorService newFixedThreadPool(int 个数) 返回线程池对象
  5. * 返回的是ExecutorService接口的实现类 (线程池对象)
  6. *
  7. * 接口实现类对象,调用方法submit (Ruunable r) 提交线程执行任务
  8. *
  9. */
  10. public class ThreadPoolDemo {
  11. public static void main(String[] args) {
  12. //调用工厂类的静态方法,创建线程池对象
  13. //返回线程池对象,是返回的接口
  14. ExecutorService es = Executors.newFixedThreadPool(2);
  15. //调用接口实现类对象es中的方法submit提交线程任务
  16. //将Runnable接口实现类对象,传递
  17. es.submit(new ThreadPoolRunnable());
  18. es.submit(new ThreadPoolRunnable());
  19. es.submit(new ThreadPoolRunnable());
  20. }
  21. }
  22. public class ThreadPoolRunnable implements Runnable {
  23. public void run(){
  24. System.out.println(Thread.currentThread().getName()+" 线程提交任务");
  25. }
  26. }

22实现线程的Callable接口方式

A:实现线程的Callable接口方式

  1. /*
  2. * 实现线程程序的第三个方式,实现Callable接口方式
  3. * 实现步骤
  4. * 工厂类 Executors静态方法newFixedThreadPool方法,创建线程池对象
  5. * 线程池对象ExecutorService接口实现类,调用方法submit提交线程任务
  6. * submit(Callable c)
  7. */
  8. public class ThreadPoolDemo1 {
  9. public static void main(String[] args)throws Exception {
  10. ExecutorService es = Executors.newFixedThreadPool(2);
  11. //提交线程任务的方法submit方法返回 Future接口的实现类
  12. Future<String> f = es.submit(new ThreadPoolCallable());
  13. String s = f.get();
  14. System.out.println(s);
  15. }
  16. }
  17. /*
  18. * Callable 接口的实现类,作为线程提交任务出现
  19. * 使用方法返回值
  20. */
  21. import java.util.concurrent.Callable;
  22. public class ThreadPoolCallable implements Callable<String>{
  23. public String call(){
  24. return "abc";
  25. }
  26. }

23线程实现异步计算

A:线程实现异步计算

  1. /*
  2. * 使用多线程技术,求和
  3. * 两个线程,1个线程计算1+100,另一个线程计算1+200的和
  4. * 多线程的异步计算
  5. */
  6. public class ThreadPoolDemo {
  7. public static void main(String[] args)throws Exception {
  8. ExecutorService es = Executors.newFixedThreadPool(2);
  9. Future<Integer> f1 =es.submit(new GetSumCallable(100));
  10. Future<Integer> f2 =es.submit(new GetSumCallable(200));
  11. System.out.println(f1.get());
  12. System.out.println(f2.get());
  13. es.shutdown();
  14. }
  15. }
  16. public class GetSumCallable implements Callable<Integer>{
  17. private int a;
  18. public GetSumCallable(int a){
  19. this.a=a;
  20. }
  21. public Integer call(){
  22. int sum = 0 ;
  23. for(int i = 1 ; i <=a ; i++){
  24. sum = sum + i ;
  25. }
  26. return sum;
  27. }
  28. }

作业测试

1.进程与线程的关系

2.多线程两种实现方式

3.多线程两种实现方式的区别

4.线程池的原理

4.线程的生命周期

如果想进一步的交流,可以加入我们的QQ群,里面有最新的学习资料,可以学习。

26_多线程_第26天(Thread、线程创建、线程池)_讲义的更多相关文章

  1. Android(java)学习笔记62:继承Thread类创建线程类

    package cn.itcast_02; /* * 该类要重写run()方法,为什么呢? * 不是类中的所有代码都需要被线程执行的. * 而这个时候,为了区分哪些代码能够被线程执行,java提供了T ...

  2. Android(java)学习笔记2:继承Thread类创建线程类

    1. 继承Thread类 创建线程类: package cn.itcast_02; /* * 该类要重写run()方法,为什么呢? * 不是类中的所有代码都需要被线程执行的. * 而这个时候,为了区分 ...

  3. 用Thread类创建线程-2

    支持原创,本系列文章均转自:http://www.blogjava.net/nokiaguy/category/38172.html 在Java中创建线程有两种方法:使用Thread类和使用Runna ...

  4. 用Thread类创建线程

    在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程, ...

  5. 【Java】学习路径46-两种创建多线程的方法、以及在匿名内部类创建线程

    两种方法: 1.创建一个继承自Thread的线程类,然后再main(不限)中构造这个线程类对象.方法在之前讲过. 2.创建一个使用Runnable接口的线程类,然后在main(不限)中构造这个Runn ...

  6. JAVA通过继承Thread来创建线程

    创建一个线程的第二种方法是创建一个新的类,该类继承Thread类,然后创建一个该类的实例. 继承类必须重写run()方法,该方法是新线程的入口点.它也必须调用start()方法才能执行. 实例 // ...

  7. 网络编程-线程-3、通过继承Thread类创建线程

    知识点:之前第一节介绍创建线程的方法是:通过threading.Thread(target=函数名不要加括号)创建一个对象,通过对象调用start方法创建并启动线程:                  ...

  8. windows多线程(十一) 更安全的创建线程方式_beginthreadex()

    一.原因分析 CreateThread()函数是Windows提供的API接口,在C/C++语言另有一个创建线程的函数_beginthreadex(),我们应该尽量使用_beginthreadex() ...

  9. Thread基础-创建线程的方式

    Java线程创建的几种简单方式 1. extends Thread类 public class ThreadDemo extends Thread{ @Override public void run ...

  10. python并发编程之线程(创建线程,锁(死锁现象,递归锁),GIL锁)

    什么是线程 进程:资源分配单位 线程:cpu执行单位(实体),每一个py文件中就是一个进程,一个进程中至少有一个线程 线程的两种创建方式: 一 from threading import Thread ...

随机推荐

  1. flutter快速入门

    好久以前就听说了dart和flutter,只是一直没有时间去研究一下,最近有了些时间就简单的研究了一下,也算是快速的入门了.dart是Google开发的语言,目前最新的版本为2.1,官网地址https ...

  2. 论文阅读---Reducing the Dimensionality of Data with Neural Networks

    通过训练多层神经网络可以将高维数据转换成低维数据,其中有对高维输入向量进行改造的网络层.梯度下降可以用来微调如自编码器网络的权重系数,但是对权重的初始化要求比较高.这里提出一种有效初始化权重的方法,允 ...

  3. 【转载】CString、BSTR和LPCTSTR之间的区别

    原文:http://www.cnblogs.com/GT_Andy/archive/2011/01/18/1938605.html 一.定义 1.CString:动态的TCHAR数组.它是一个完全独立 ...

  4. 【CJOJ2433】陌上花开 树状数组套替罪羊树

    [CJOJ2433]陌上花开 树状数组套替罪羊树 蛤?bzoj?没权限QAQ 蛤?CDQ?看了好久没看懂QwQ 好吧我会拿cdq再写一遍的 为啥我感觉这东西比cdq好写 只好拿树状数组套替罪羊树水水了 ...

  5. SQL Server 日期格式和日期操作

    SQL Server发展至今,关于日期的格式的控制方法,有传统的方法,比如CONVERT(),也有比较便利的新方法,比如FORMAT():同样,关于日期的操作函数,也分为传统方法:DATEADD()等 ...

  6. Form,tagName和nodeName的区别

    首先介绍DOM里常见的三种节点类型(总共有12种,如docment):元素节点,属性节点以及文本节点,例如<h2 class="title">head</h2&g ...

  7. 深入浅出js中的this

    Q:this是什么? A:this是Javascript语言的一个关键字,它代表函数运行时,自动生成的一个内部对象,在每个 function 中自动根据作用域(scope) 确定, 指向的是此次调用者 ...

  8. 《Pro SQL Server Internals, 2nd edition》的CHAPTER 1 Data Storage Internals中的Data Pages and Data Rows(翻译)

    数据页和数据行 数据库中的空间被划分为逻辑8KB的页面.这些页面是以0开始的连续编号,并且可以通过指定文件ID和页号来引用它们.页面编号都是连续的,这样当SQL Server增长数据库文件时,从文件中 ...

  9. 第七章 用户输入和while循环

    7.1函数input()的工作原理 函数默认输入为字符串string,如果需使用数字,需用int进行类型转换 7.2 while循环 while是根据条件的真假判断是否进入执行 使用标志: 使用bre ...

  10. 08-matplotlib-颜色与样式

    import numpy as np import matplotlib.pyplot as plt ''' 颜色: - 八种内置默认颜色, 缩写 b :blue g :green r :red c ...