java多线程

并发与并行

并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行
并行:一组程序按独立异步的速度执行,无论从微观还是宏观,程序都是一起执行的。
对比:并发是指:在同一个时间段内,两个或多个程序执行,有时间上的重叠(宏观上是同时,微观上仍是顺序执行)

进程与线程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础

线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

java的线程

java多线程机制

多线程是指一个应用程序同时存在几个执行体,按照几条不同的执行线索共同工作的情况。java多线程机制,它使得编程人员可以很方便的开发出具有多线程功能、能同时处理多个任务的强大应用程序。java内置对多线程的支持,java虚拟机可以快速的从一个线程切换到另一个线程。这些线程的轮流执行使得每个线程都有机会使用cpu资源。

java的主线程

每个java程序都含有一个线程,那就是主线程(main线程)。Java应用程序都是从主类main方法执行的,当jvm加载代码,发现卖弄方法之后,就会启动一个线程,这个线程就是主线程,负责执行main方法。如果在主线程里面创建其他线程,就会在主线程和其他线程来回切换,直到其他所有线程结束才会结束主线程。

线程的生命周期

  • 运行
    线程创建之后只占有了内存资源,在JVM管理的线程中并没有刚刚创建的这个线程,只有这个线程调用start()方法后,JVM才知道有一个新线程进入队列等待cpu调用。

  • 中断原因(4种)

    • jVM把cpu资源切换给其他线程。
    • 线程使用cpu期间,执行了sleep(int millsecond)方法,使当前线程进入休眠状态,调用该方法之后会立即让出cpu,经过参数millsecond指定的毫秒后,重新加入队列等待cpu。
      -使用cpu期间,执行了wait()方法,使得当前进程进入等待状态,这个等待个sleep()不同,这个等待需要其他线程调用notify()方法唤醒该线程,此线程才会重新进入队列,等待cpu。
      线程使用cpu期间,执行了某个操作进入阻塞状态,例如(读、写、打印等),只有这些造成阻塞的原因完成,这个线程才会进入队列,等待cpu。

创建线程(3种)

继承Thread类实现线程创建

  • 一种是创建一个类继承Thread类,这种继承可以重复使用!
  • 一种是直接使用匿名内部类继承,这种类型只能使用一次,每次使用都要重新创建
  • 不论哪种都需要重写run()方法,并且在定义之后调用start()方法,把这个线程调入线程队列等待调用。

下面我们使用匿名内部类创建一个打印100以内的奇数线程,使用类继承Thread类打印100内的偶数线程。

package hello;public class Hello {public static void main(String[] args) {Thread1 thread1 = new Thread1();Thread thread = new Thread() {@Overridepublic void run() {for (int i = 0; i < 100; i++) {if (i % 2 == 1) {//打印线程名,线程名是从0开始的System.out.println(Thread.currentThread().getName() + ":" + i);}}}};thread1.start();thread.start();}
}class Thread1 extends Thread{@Overridepublic void run() {super.run();for(int i=0;i<100;i++){if (i%2==0){System.out.println(Thread.currentThread().getName()+":"+i);}}}
}

方法说明
start()启动当前线程;调用当前线程的run()方法
run():需要重写Thread类中的此方法,将创建线程需要执行的操作声明在此方法中
currentThread():返回执行当前代码的线程
getName():获取当前线程的名字
setName(String name):设置当前线程的名字
yield():释放当前CPU的执行权
join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完之后,线程a在结束阻塞状态
sleep(int millitime):让当前线程“睡眠”指定的millitime毫秒。在指定的millitime毫秒时间内,当前进程是阻塞状态
isAlive():判断当前线程是否存活(线程执行完之前都是存活的)

实现Runnable接口

  • 我们还是创建两个线程,一个打印奇数,一个打印偶数,但是有一个线程每次调用会睡眠(阻塞)10ms。
  • 使用实现接口Runnable方法,必须重写run()方法。
package hello;public class Hello {public static void main(String[] args) {Thread thread = new Thread(new MyThread1());/*Thread thread = new Thread(new MyThread1());就相当于 ,就是创建实现类的对象,再把这个对象用Thread()构造器的方法创建MyThread1 myThread1 = new MyThread1();Thread thread = new Thread(myThread1);*/Thread thread1 = new Thread(new MyThread2());thread.start();thread1.start();}
}class MyThread1 implements Runnable{@Overridepublic void run() {for(int i=0;i<100;i++) {if (i % 2 == 1) {System.out.println(Thread.currentThread().getName() + ":" + i);try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}}
}class MyThread2 implements Runnable{@Overridepublic void run() {for(int i=0;i<100;i++) {if (i % 2 == 0) {System.out.println(Thread.currentThread().getName() + ":" + i);}}}
}

开发中,优先选择实现Runnable接口的方式创建线程

原因:

实现Runnable接口的方式没有类的单继承性的局限性(一个类只能继承一个父类,继承了Thread类就不能在继承其他类了)
实现Runnable接口的方式更适合来处理多个线程之间有共享数据的情况

实现Callable接口

Runnable接口是没有返回值的 Callable有返回值,可以抛出异常
Thread类并不接受Callable对象。可以使用FutureTask类实现Runnable接口和Future接口
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

Java的类是单继承的设计,如果采用继承Thread的方式实现多线程,则不能继承其他的类,采用接口能够更好的实现数据共享

FutureTask有两个构造函数,一个以Callable为参数,另外一个以Runnable为参数。

我理解的就是通过FutureTask把Callable变成通过Runnable接口创建的,因为FutureTask继承了Runnable接口。主要原因是Thread类不接受Callable创建,但是接受Runnable创建的线程。

package hello;import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;public class Hello {public static void main(String[] args) throws Exception {MyThread1 myThread1 = new MyThread1();FutureTask<Integer> futureTask = new FutureTask<>(new MyThread1());new Thread(futureTask).start();//开启线程System.out.println(futureTask.get());//获取返回值}
}class  MyThread1 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int count = 0;for (int i = 1;i<100;i++){if (i%3==0){count++;}}return count;}
}

线程池

线程池的执行过程

  • 实例
package hello;import java.util.concurrent.*;public class Hello {public static void main(String[] args) throws Exception {//创建线程池ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 4, 5, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(2),new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {Thread thread = new Thread(r);thread.setName("myThread");return thread;}},new ThreadPoolExecutor.AbortPolicy());//threadPoolExecutor.submit();threadPoolExecutor.execute(new MyThread());//提交任务threadPoolExecutor.shutdown();//关闭线程池}
}class MyThread implements Runnable{@Overridepublic void run() {for (int i=0;i<10;i++){System.out.println(i);}}
}

在此我向大家推荐一个架构学习交流圈。交流学习伪鑫:539413949(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

Java多线程【三种实现方法】相关推荐

  1. Java list三种遍历方法性能比较

    从c/c++语言转向java开发,学习java语言list遍历的三种方法,顺便测试各种遍历方法的性能,测试方法为在ArrayList中插入1千万条记录,然后遍历ArrayList,发现了一个奇怪的现象 ...

  2. java list三种遍历方法性能比較

    从c/c++语言转向java开发,学习java语言list遍历的三种方法,顺便測试各种遍历方法的性能,測试方法为在ArrayList中插入1千万条记录,然后遍历ArrayList,发现了一个奇怪的现象 ...

  3. java map集合遍历方法,Java的Map集合的三种遍历方法

    集合的一个很重要的操作---遍历,学习了三种遍历方法,三种方法各有优缺点~~ 1. package com.myTest.MapText; import java.util.Collection; i ...

  4. Java三种随机数生成方法

    java的三种随机数生成方式 随机数的产生在一些代码中很常用,也是我们必须要掌握的.而java中产生随机数的方法主要有三种: 第一种:new Random() 第二种:Math.random() 第三 ...

  5. JAVA中三种URL连接方法

    Java的网络类可以让你通过网络或者远程连接来实现应用.而且,这个平台现在已经可以对国际互联网以及URL资源进行访问了.Java的URL类可以让访问网络资源就像是访问你本地的文件夹一样方便快捷.我们通 ...

  6. JAVA爬虫三种方法

    文章目录 前言 一.JDK 二.HttpClient 三.Jsoup 总结 前言 记录JAVA爬虫三种方式 一.JDK 使用JDK自带的URLConnection实现网络爬虫. public void ...

  7. Java数组的三种定义方法

    Java数组的三种定义方法 1.第一种适合不用初始化的数组.数组特别长的时候,不初始化,值都是默认值. 2.第二种定义适合直接初始化数组 3.第三种匿名数组适合直接给方法传入参数时使用 1.第一种适合 ...

  8. JAVA vector的遍历_谈谈vector容器的三种遍历方法

    说明:本文仅供学习交流.转载请标明出处.欢迎转载! vector容器是最简单的顺序容器,其用法相似于数组.实际上vector的底层实现就是採用动态数组.在编敲代码的过程中.经常会变量容器中的元素,那么 ...

  9. JAVA抽象类实例化对象实现接口的三种调用方法

    在笔者的学习过程中抽象类实例化对象实现接口,笔者发现了三种表示方法.第一种是要实例化接口和抽象类,再用实例化的对象调用重写的的方法,这比较繁琐:第二种是直接实例化抽象类,将抽象类进行强转成对象,因为对 ...

  10. Java多线程——三个多线程案例总结

    Java多线程--三个多线程案例总结   非常经典的三道多线程案例   1.写两个线程,一个线程打印1-52,另一个线程打印A~Z,     打印顺序为:12A34B-5152Z   2.编写一个程序 ...

最新文章

  1. PHP入门 1 phpstudy安装与配置站点
  2. 基于Matlab的神经网络结合遗传算法在非线性函数极值寻优中的应用
  3. 【SpringBoot】项目实现热部署的两种方式
  4. 解读MySQL 8.0新特性:Skip Scan Range
  5. 距离一个优秀程序员,你还差多少?
  6. 关于Oracle分区的一篇文章
  7. 图解深度学习-三种梯度下降法可视化(BGD,SGD,MBGD)
  8. 全球及中国锗行业发展规模与前景调查分析报告2022-2028年
  9. 使用octotree 出现Error: Connection error octotree解决办法
  10. Typora下载、安装与使用
  11. 统计学权威盘点过去50年最重要的统计学思想,因果推理、bootstrap等上榜,Judea Pearl点赞
  12. 华为android9使用外置存储卡,华为mate9如何删除内存卡文件?华为手机清理内存教程...
  13. python实现随机抽奖游戏
  14. 调整HTML5画布中图像的大小
  15. 利用浏览器检查获取网页视频
  16. html在线ocr文字识别源码,如何用OCR文字识别软件把图像转换成HTML
  17. 黑苹果2k显示器开启hidpi_黑苹果开启硬件加速
  18. 抓铁有力榜:踏石有印,抓铁留痕
  19. yy账号找回方法详解
  20. HDU 6194 后缀数组+单调栈

热门文章

  1. python爬虫实践记录-基于requests访问翻译网页爬取结果
  2. PMP认证与企业项目管理的进化之旅
  3. 阿里巴巴今晚发布财报 2019财年全年业绩也将一并公布
  4. flash 生成图片上传
  5. VirtualBox虚拟机与主机互通,并且虚拟机又能上网
  6. 微信支付——微信退款实战教程(Java版)
  7. 10天免登录操作,保存/取消cookie
  8. 关于JavaScript中的Date你需要知道的一切
  9. 种子搜索uTorrent被发现存在重大漏洞
  10. vue data拓展运算符_您应该知道的R data.table符号和运算符