多线程

  线程是程序执行的一台路径,一个进程中可以包含多条线程

  多线程并发执行可以提高程序的效率,可以同时完成多项工作

多线程的应用背景

  红蜘蛛同时共享屏幕给多个电脑

  迅雷开启多条线程一起下载

  QQ同时和多个人一起视频

  服务器同时处理多个客户端请求

多线程并行和并发

  并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行(需要多核CPU)

  并发是指两个任务都请求运行,而处理器只能接受一个任务,就把这两个任务轮流进行,由于时间间隔较短,使人感觉两个任务都在运行

  比如我跟两个网友聊天,左手操作一个电脑跟甲聊,同时右手用另一台电脑跟乙聊天,这就叫并行

  如果用一台电脑我先给甲发个信息,然后立刻再给乙发信息,然后再跟甲聊,再跟乙聊。这就叫并发

java程序运行原理和jvm的启动

  *java命令启动java虚拟机,启动jvm,等于启动了一个应用程序,也就是启动了一个进程,该进程会自动启动一个 “ 主线程 ”,然后主线程去调用某个类的 main 方法

  *jvm启动至少启动了垃圾回收线程和主线程,所以是多线程的

多线程程序实现

 1. 继承Thread

    定义类继承Thread

    重写run方法

    把新线程要做的是写在run方法中

    创建线程对象

    开启新线程,内部会自动执行run方法

public class demo1_thread {public static void main(String[] args) {mythread mt1 =new mythread(); //创建thread类的子类对象mt1.start();  //开启线程for(int i=0;i<1000;i++){System.out.println("bbbbb");}}}
class mythread extends Thread{  //继承threadpublic void run(){            //重写run方法for(int i=0;i<1000;i++){System.out.println("aaaaaaaaaa");}}
}

案例

 2. 实现runnable

    定义类显示Runnable接口

    实现run方法

    把新线程要做的事写在run方法中

    创建自定义的Runnable的子类对象

    创建Thread对象,传入Runnable

    调用start()开启新线程,内部会自动调用Runnable的run方法

public class demo2_Runnnbale {public static void main (String args []){myrunnbale mr =new myrunnbale();  //创建runnable的子类对象new Thread(mr).start();            //将其当做参数传递给thread的构造函数,并开启线程for (int i = 0; i < 1000; i++) {System.out.println("cc");}}
}
class myrunnbale implements Runnable{@Overridepublic void run() {for (int i = 0; i < 1000; i++) {System.out.println("aaaaaaaaaaaaaa");}}}

案例

实现Runnable的原理

  看Thread类的构造函数,传递了Runnable接口的引用

  通过init()方法找到传递的target给成员变量的target赋值

  查看run方法,发现run方法中有判断,如果target不为null就会太哦用Runnable接口子类对象的run方法

两种方式的区别

  1.继承Thread:由于子类重写了Thread类的run(),方太哦用start()时,直接找子类的run()方法

  2.实现Runnable:构造函数中传入了Runnable的引用,成员变量记住了它,start()调用run()方法时内部成员变量Runnable引用是否为空,不为空编译时看的siRunnable的run(),运行时执行的狮子类的run()方法

继承Thread:

  好处是:可以直接使用Thread类中的方法,代码简单

  弊端是:如果已经有父类,就不能用这种方法

实现Runnable接口:

  好处是:即使自己定义的县城类有了父类也没关系,因为有了父类也可以实现接口,而且接口是可以多实现的

  弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码复杂

匿名内部类实现线程

  1.继承Thread方法 

  2.实现Runnable方法

public class demo3_Thread {public static void main(String[] args) {new Thread(){          //继承Thread方法public void run(){    //重写run方法for (int i = 0; i < 3000; i++) {System.out.println("aaaaaaaaa");}}}.start();  //开启线程new Thread(new Runnable(){public void run(){for (int i = 0; i < 3000; i++) {System.out.println("bbb");}}}).start();}}

案例

获取名字

  1.通过geyName()方法获取线程对象的名字

设置名字

  2.通过构造方法函数可以传入String类型的名字

  通过setName(String)方法可以设置线程对象的名字

public class demo1_Name {public static void main (String args[]){new Thread("大哥"){public void run(){System.out.println(this.getName()+"aaaaaaaa");}}.start();new Thread(){public void run(){this.setName("战三");System.out.println(this.getName()+"bb");}}.start();Thread t1= new Thread("大哥"){public void run(){System.out.println(this.getName()+"aaaaaaaa");}};t1.setName("李");t1.start();}
}

案例

获取当前线程的对象

  Thread.currentThread(),主线程也可以获取

public class demo2_currentthread {public static void main(String[] args) {new Thread("毛毛"){public void run (){System.out.println(getName()+"...aaaaaaa");}}.start();new Thread(new Runnable(){public void run(){//Thread.currentThread()获取当前正在执行的线程System.out.println(Thread.currentThread().getName()+"...bb");}}).start();Thread.currentThread().setName("主线程");System.out.println(Thread.currentThread().getName());}}

案例

休眠线程

  Thread.sleep(毫秒,纳秒),控制当前线程休眠若干毫秒1秒 =1000 * 1000 * 1000纳秒  1000000000

public class demo3_seelp {public static void main(String[] args) throws InterruptedException {//demo1();new Thread(){public void run(){for (int i = 20; i >=0; i--) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch block
                        e.printStackTrace();}System.out.println(getName()+"...a");}}}.start();new Thread(){public void run(){for (int i = 20; i >=0; i--) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch block
                        e.printStackTrace();}System.out.println(getName()+"..bb");}}}.start();}public static void demo1() throws InterruptedException {for(int i=20;i>=0;i--){Thread.sleep(1000);System.out.println("倒计时"+i+"秒");}}}

案例

守护线程

  setDaemon(),设置一个线程为守护线程,该线程不会单独执行,当其他飞守护线程都执行结束后,自动退出

public class demo4_daemon {public static void main(String[] args) {Thread t1 =new Thread(){public void run(){for (int i = 0; i < 2; i++) {System.out.println(getName()+"..aaaaaaaa");}}};Thread t2 =new Thread(){public void run(){for (int i = 0; i < 50; i++) {System.out.println(getName()+"..bb");}}};t2.setDaemon(true); //当传入true就是意味着设置为守护线程
        t1.start();t2.start();}}

案例

加入线程

  join(),当前线程暂停,等待指定的线程执行结束后,当前线程在继续

  join(int),可以等待指定的毫秒之后继续

public class demo5_Join {public static void main(String[] args) {final Thread t1 =new Thread(){public void run (){for(int i=0; i<10 ;i++){System.out.println(getName()+"...aaaaaaaaa");}}};Thread t2 =new Thread(){public void run (){for(int i=0; i<10 ;i++){if(i==2){try {t1.join(1);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(getName()+"...bb");}}};t1.start();t2.start();}}

案例

礼让线程

yield让出cpu

设置线程的优先级

  setPriority() 设置线程的优先级

N1.setPriority(Thread.MIN_PRIORITY);            //设置最大的线程优先级
N2.setPriority(Thread.MAX_PRIORITY);           //设置最小线程优先级

同步代码块

什么情况下需要同步

  当多线程并发,有多段代码同时执行是,我们希望某一段代码执行的过程中cpu不要切换到其他线程工作,这是就需要同步

  如果两端代码是同步的,那么同一时间值执行一段,在一段代码每执行结束之前,不会执行另一端代码

同步代码块

  使用synchronized关键字加上一个锁对象来定义一段代码,这就叫同步代码块

  多个同步代码块如果使用相同的锁对象,那么他们就是同步的

public class test_sybchronized {public static void main(String[] args) {final pritner p1=new pritner();new Thread(){public void run(){while(true){p1.print1();    }}}.start();new Thread(){public void run(){while(true){p1.print2();    }}}.start();}}
class pritner{
demo d=new demo();public void print1(){synchronized (d) {System.out.println("学习");}}public void print2(){System.out.println("学校");}
}class demo{}

案例

同步方法

*使用synchronized 关键字修饰一个方法,该方法中所有的代码都是同步的

public class test2_sybchronized {public static void main(String[] args) {final pritner2 p1=new pritner2();new Thread(){public void run(){while(true){p1.print1();    }}}.start();new Thread(){public void run(){while(true){p1.print2();    }}}.start();}}
class pritner2{//非静态放入同步方法的锁对象是this//静态的锁不方法的锁对象是:该类的字节码对象public synchronized void print1(){System.out.print("学");System.out.print("习");System.out.print("的");System.out.print("心");System.out.print("\r\n");}public void print2(){synchronized (this) {        System.out.print("学");System.out.print("校");System.out.print("的");System.out.print("路");System.out.print("上");System.out.print("\r\n");}}}

案例

线程安全问题

  多线程并发操作同一数据时,就有可能出现线程安全问题

  使用同步技术可以解决这种问题,把操作数据的代码进行同步,不要多个线程一起操作

public class test2_ticket {public static void main(String[] args) {new ticket().start();new ticket().start();new ticket().start();new ticket().start();}}
class ticket extends Thread{private static int ticket =100;public void run(){while(true){synchronized (ticket.class) {    if(ticket <=0){break;}try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch block
                e.printStackTrace();}System.out.println(getName() + "...这是第" + ticket-- + "号票");}}}
}

案例

死锁

多线程同步的时候,如果同步代码嵌套,使用相同锁,就有可能出现死锁

public class test3_ {private static String s1 ="筷子左";private static String s2 ="筷子右";public static void main(String[] args) {new Thread(){public void run (){while(true){synchronized (s1) {System.out.println(getName()+"读取"+s1+"等待"+s2);    synchronized (s2) {System.out.println(getName()+"拿到"+s2+"吃");    }}}}}.start();new Thread(){public void run (){while(true){synchronized (s2) {System.out.println(getName()+"读取"+s2+"等待"+s1);    synchronized (s1) {System.out.println(getName()+"拿到"+s1+"吃");    }}}}}.start();}}

案例

转载于:https://www.cnblogs.com/JungTan0113/p/10970951.html

2019-06-03 Java学习日记 day24 多线程相关推荐

  1. 2019-06-03 Java学习日记之多线程下GUI

    多线程下 单例设计模式: 保证类在内存中只有一个对象 如何保证类在内存中只有一个对象呢? 1.控制类的创建,不让其他类来创建本类的对象 2.在本类中定义一个本类的对象,Singleton s 3.提供 ...

  2. 2019-06-02 Java学习日记之多线程上

    多线程程序实现的方式1: 1.继承Thread 定义类继承Tread 重写run方法 把新线程要做的事写在run方法中 创建线程对象 开启新线程,内部会自动执行run方法 package com.th ...

  3. Java学习日记1——基础认知

    Java学习日记1--基础认知 学习Java阶段,如果发现不正确的描述,还请指正! 首先附上Java相关下载链接和配置教程链接 Java相关软件工具下载地址:官方下载 Java环境配置(win10配置 ...

  4. Java学习日记-Day01

    Java学习日记-Day01 Java语言概述 比特(byte)与字节 内存 Java基础知识图解 人机交互方式 常用的DOS命令 常用快捷键 计算机编程语言介绍 第一代语言 第二代语言 第三代语言 ...

  5. 尚学堂Java学习日记Day3

    尚学堂Java学习日记Day3 第三天老师先回顾了昨天的内容我从回顾中掌握了新的知识 如下图所示 int与double计算,输出类型为double的不同结果 会把int转成double类型的,这是隐式 ...

  6. Java学习日记:UI篇(6)--谢尔宾斯基地毯图

    Java学习日记:UI篇(6)–谢尔宾斯基地毯图 引言:谢尔宾斯基地毯是数学家谢尔宾斯基提出的一个分形图形,谢尔宾斯基地毯和谢尔宾斯基三角形基本类似,不同之处在于谢尔宾斯基地毯采用的是正方形进行分形构 ...

  7. 【日记】Java学习日记(第63天)持续无聊更新

    前言 Youtube上EJ Media(up主)的视频我依次学完了HTML.CSS.Javascript.Jquery.觉得他教得挺好的(短小精悍),就继续学他教的JAVA.感觉EJ教的都是些语法什么 ...

  8. Java学习笔记5-1——多线程

    目录 前言 核心概念 线程创建 继承Thread类 实现Runnable接口 上述两个方法小结 实现Callable接口 并发问题简介 静态代理模式 线程状态 线程停止(stop) 线程休眠(slee ...

  9. 黑马程序员--Java学习日记之网络编程

     ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.网络编程概述 1.计算机网络 计算机网络是指将地理位置不同的具有独立功能的多台计算机及 ...

最新文章

  1. Laplace数值逆运算的讨论
  2. Python 3基础教程15-读文件内容
  3. springboot入门知识点(一)
  4. 【Python②】python之首秀
  5. CurvLearn开源 | 阿里妈妈曲率学习框架详解
  6. numpy将所有数据变为0和1_Numpy库学习
  7. CentOS7如何安装vsftpd
  8. 2010年6月计算机组织与结构,2010 计算机组织与体系结构课程设计.doc
  9. 常见input输入框 点击 发光白色外阴影 focus
  10. CCF中国计算机学会推荐国际学术期刊与会议
  11. 《善用佳软:高效能人士的软件应用之道》一第2章 办公软件:核心应用,实用技巧...
  12. 怎样把pdf转换成word-多语言ocr支持
  13. 易基因|深度综述:m6A RNA甲基化在大脑发育和疾病中的表观转录调控作用
  14. windows11系统 “任务管理器已被管理员禁用”怎么解决
  15. python爬虫入门-环境配置
  16. Bootstrap排版之标题
  17. 最简单的11g Active DataGuard(ADG)搭建配置过程(项目步
  18. 农业物联网发展有哪些问题
  19. 计算机怎样检查视力,电脑视力表同样测视力 测试方法要正确
  20. python算法习题(十):木材加工

热门文章

  1. [K/3Cloud]进度条控件编程接口
  2. Android开发必看知识,不看后悔
  3. [转载红鱼儿]kbmmw 开发点滴:kbmMW:Unknown property:indexes
  4. 一起谈.NET技术,浅析购物车的实现
  5. jquery之empty()与remove([expr])区别
  6. 数据绑定控件之DataList
  7. Javascript 获取浏览器窗口中文档(视口)可用尺寸的方法
  8. 汇编语言--adc指令
  9. 设计一个shell程序,在/userdata目录下建立50个目录,并对每个目录给754权限!
  10. 在switch case 语句中能否使用continue 关键字?为什么?