博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVAV自学日志02(多线程)
阅读量:3948 次
发布时间:2019-05-24

本文共 9577 字,大约阅读时间需要 31 分钟。

进程(Process)和线程(Thread)的有什么何区别

定义

  1. 进程是具有一定独立功能的的程序,进程是系统进行资源分配和调度的一个独立单元。

  2. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源

区别

  1. 一个程序至少有一个进程,一个进程至少有一个线程.
  2. 线程的划分尺度小于进程,使得多线程程序的并发性高。
  3. 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
  4. 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是进程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
  5. 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。

普通方法调用和多线程

在这里插入图片描述

线程实现(重点)

继承Thread类(重点)

实现Runnable接口(重点)
实现Callable接口

线程的创建

1.继承Thread类(重点)

第一步:自定义线程类继承Thread类。

第二步:重写run()方法,编写线程执行体。
第三步:创建线程对象,调用start()方法启动线程。

package com.tjrac.demo01;//第一步:自定义线程类继承Thread类。//第二步:重写run()方法,编写线程执行体。//第三步:创建线程对象,调用start()方法启动线程。方法启动线程public class TestThread1 extends  Thread{
@Override public void run() {
for(int i=0;i<20;i++){
System.out.println("我在看代码"); } } public static void main(String[] args) {
//创建线程对象 TestThread1 testThread1=new TestThread1(); //调用对象的start方法 testThread1.start(); for(int i=0;i<200;i++){
System.out.println("我学习多线程"+i); } }}

实战下载图片

package com.tjrac.demo01;import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;import java.net.URL;//第一步:自定义线程类继承Thread类。//第二步:重写run()方法,编写线程执行体。//第三步:创建线程对象,调用start()方法启动线程。方法启动线程public class TestThread1 extends  Thread{
private String url;//网络图片的地址 private String name;//保存的文件名 public TestThread1(String url,String name){
this.url=url; this.name=name; } //下载线程的执行体 @Override public void run() {
WedDownlaoder wedDownlaoder= new WedDownlaoder(); wedDownlaoder.Downlaoder(url,name); System.out.println(name+"下载完成"); } public static void main(String[] args) {
//创建线程对象 TestThread1 t1=new TestThread1("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1577168219347&di=5bb4508ef618b0da3aed3d042eb8997e&imgtype=0&src=http%3A%2F%2Fimaegs.creditsailing.com%2Farticle%2F121%2F57_ua3ao__.jpg","陈声铭用多线程下载的图片01.jpg"); TestThread1 t2=new TestThread1("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1577168219347&di=5bb4508ef618b0da3aed3d042eb8997e&imgtype=0&src=http%3A%2F%2Fimaegs.creditsailing.com%2Farticle%2F121%2F57_ua3ao__.jpg","陈声铭用多线程下载的图片02.jpg"); TestThread1 t3=new TestThread1("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1577168219347&di=5bb4508ef618b0da3aed3d042eb8997e&imgtype=0&src=http%3A%2F%2Fimaegs.creditsailing.com%2Farticle%2F121%2F57_ua3ao__.jpg","陈声铭用多线程下载的图片03.jpg"); //调用对象的start方法 t1.start(); t2.start(); t3.start(); }}//下载器class WedDownlaoder{
//下载方法 public void Downlaoder(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) {
e.printStackTrace(); System.out.println("Downlaoder方法异常"); } }}

总结:线程开启不一定执行,由CPU调度执行,不推荐用Thread类,因为要不免单继承的局限性。

2.实现Runnable接口(重点)

第一步:实现Runnable接口。

第二步:重写run()方法。
第三步:将线程执行的接口放入接口实现类。

package com.tjrac.demo01;//第一步:实现Runnable接口。//第二步:重写run()方法。//第三步:将线程执行的接口放入接口实现类。public class TestRunnable01 implements Runnable{
@Override public void run() {
for(int i=0;i<20;i++){
System.out.println("下载完成"); } } public static void main(String[] args) {
//创建Runnable接口的实现类对象 TestRunnable01 testRunnable = new TestRunnable01(); //创建线程对象,通过线程对象来启动线程 new Thread(testRunnable).start(); for(int i=0;i<500;i++){
System.out.println("下载完成"+i); } }}

实战下载图片(荣耀战魂)

package com.tjrac.demo01;import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;import java.net.URL;public class TestRunnable02 implements Runnable{
private String url;//网络图片的地址 private String name;//保存的文件名 public TestRunnable02(String url,String name){
this.url=url; this.name=name; } //下载线程的执行体 @Override public void run() {
RunnableDownlaoder runnableDownlaoder= new RunnableDownlaoder(); runnableDownlaoder.Downlaoder(url,name); System.out.println(name+"下载完成"); } public static void main(String[] args) {
//创建线程对象 TestRunnable02 t1=new TestRunnable02("https://imgsa.baidu.com/forum/pic/item/8a13632762d0f703b83556ae07fa513d2697c539.jpg","陈声铭用多线程下载的图片04.jpg"); //调用对象的start方法 new Thread(t1).start(); }}//下载器class RunnableDownlaoder{
//下载方法 public void Downlaoder(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) {
e.printStackTrace(); System.out.println("Downlaoder方法异常"); } }}

总结:推挤使用Runnable接口,方便灵活,可以一个对象被多个线程使用,但是会出现多线程并发的问题。在这里插入图片描述

多个线程同时操作一个对象实战
卖火车票

package com.tjrac.demo01;//多个线程同时操作一个对象//卖火车票public class TestRunnable03 implements Runnable {
private int ticket=10; @Override public void run() {
//模拟延时 try {
Thread.sleep(200); } catch (InterruptedException e) {
e.printStackTrace(); } while (true) {
if(ticket<=0){
break; } System.out.println(Thread.currentThread().getName()+"买到了第"+ticket--+"票"); } } public static void main(String[] args) {
TestRunnable03 testRunnable03=new TestRunnable03(); new Thread(testRunnable03,"陈声铭").start(); new Thread(testRunnable03,"雷志明").start(); new Thread(testRunnable03,"唐可明").start(); new Thread(testRunnable03,"陈笑").start(); }}
3.实现Callable接口

在这里插入图片描述

实战下载图片

package com.tjrac.demo01;import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;import java.net.URL;import java.util.concurrent.*;public class TestCallable01 implements Callable
{
private String url;//网络图片的地址 private String name;//保存的文件名 public TestCallable01(String url,String name){
this.url=url; this.name=name; } //下载线程的执行体 @Override public Boolean call() {
RunnableDownlaoder runnableDownlaoder= new RunnableDownlaoder(); runnableDownlaoder.Downlaoder(url,name); System.out.println(name+"下载完成"); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建线程对象 TestCallable01 t1=new TestCallable01("https://imgsa.baidu.com/forum/w%3D580%3B/sign=16a0044f35f33a879e6d0012f6671138/37d12f2eb9389b508c5b672d8a35e5dde7116e2d.jpg","陈声铭用多线程下载的图片05.jpg"); //创建执行服务 ExecutorService ser = Executors.newFixedThreadPool(1); //提交执行 Future
r1=ser.submit(t1); //获取结果 boolean rs1=r1.get(); //关闭服务器 ser.shutdownNow(); }}//下载器class CallableDownlaoder{
//下载方法 public void Downlaoder(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) {
e.printStackTrace(); System.out.println("Downlaoder方法异常"); } }}

线程的5个状态

  1. new
  2. 就绪状态
  3. 运行状态
  4. 阻塞状态
  5. dead
    在这里插入图片描述
    在这里插入图片描述
    停止线程
    在这里插入图片描述
package com.kuang.springbootmybatis.controller;public class TestRunnable03 implements Runnable {
public boolean flag=true; @Override public void run() {
int ticket=0; while (flag) {
System.out.println("Thread...run"+ticket++); } } public void stop(){
this.flag=false; } public static void main(String[] args) {
TestRunnable03 testRunnable03=new TestRunnable03(); new Thread(testRunnable03).start(); for (int i=0;i<=10000;i++){
System.out.println("main"+i); if(i==9000){
testRunnable03.stop(); System.out.println("线程停止"); } } }}

线程休眠

  1. sleep指定当前线程阻塞速秒。
  2. sleep存在异常InterruptedException。
  3. sleep时间到达之后线程进入就绪状态。
  4. sleep可以用来模拟网络延时,倒计时等。
  5. 每一个对象都有一个锁,sleep不会释放锁。
package com.kuang;import jdk.internal.dynalink.beans.StaticClass;import java.text.SimpleDateFormat;import java.util.Date;public class TestSleep {
public static void main(String[] args){
Date data=new Date(System.currentTimeMillis()); while(true){
try {
Thread.sleep(1000); System.out.println(new SimpleDateFormat("HH:mm:ss").format(data)); data=new Date(System.currentTimeMillis()); } catch (InterruptedException e) {
e.printStackTrace(); } } } //倒计时 public static void tenDown() throws InterruptedException {
int num=10; while(true){
Thread.sleep(1000); System.out.println(num--);; if(num<=0){
break; } } }}

线程礼让

  1. 礼让线程,让当前正在执行的线程暂停,但不阻塞。
  2. 将线程从运行状态转为就绪状态。
  3. 让cpu重新调度,礼让不一定成功!看CPU心情
package com.kuang;public class TestYield {
public static void main(String[] args){
MyYield myYield=new MyYield(); new Thread(myYield,"a").start(); new Thread(myYield,"b").start(); }}//礼让class MyYield implements Runnable{
@Override public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始"); Thread.yield(); System.out.println(Thread.currentThread().getName()+"线程结束"); }}

join

  1. join合并线程,待该线程执行完成后,再执行其他线程,其他线程阻塞。
  2. 就是插队

转载地址:http://ilrwi.baihongyu.com/

你可能感兴趣的文章
linux学习之shell字符串大小写转换
查看>>
Linux下用base64对字符串进行加密解密
查看>>
linux学习之/usr/bin/expect 的使用及传参数
查看>>
Hadoop-MapReduce的工作原理
查看>>
H5走迷宫小游戏
查看>>
mysql建表 表名与关键字冲突
查看>>
mysql 创建单表外键关联多表
查看>>
postman使用
查看>>
ClassNotFoundException和NoClassDefFoundError的区别
查看>>
Tomcat Connector三种运行模式(BIO, NIO, APR)的比较和优化
查看>>
Maven 使用Assembly 配置详细解释
查看>>
调试打包jar方法
查看>>
MVC RPC SOA 和微服务架构的区别
查看>>
HTTP与TCP的区别和联系
查看>>
解决Cannot resolve method 'onMethod_'
查看>>
VMware 虚拟机NAT模式如何设置网络连接
查看>>
cloud2020
查看>>
@bean和@component的理解
查看>>
spring注解@Primary与@Qualifier
查看>>
annotation之@Autowired、@Inject、@Resource三者区别
查看>>