多线程程序实现的方式1:

1、继承Thread

  定义类继承Tread

  重写run方法

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

  创建线程对象

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

package com.thread;public class Demo1 {public static void main(String[] args) {MyThread mt = new MyThread();                //4、创建Thread类的子类对象mt.start();                                 //5、开启线程for (int i = 0; i < 1000; i++) {System.out.println("bbbb");}}
}
class MyThread extends Thread {                        //1、继承Tpublic void run() {                                //2、重写run方法for (int i = 0; i < 1000; i++) {            //3、将要执行的代码写在run方法中System.out.println("aaaaaaaaaa");}}
}

多线程程序实现的方式2:

2、实现Runnable

定义类实现Runnable接口

实现run方法

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

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

创建Thread对象,传入Runnable

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

package com.thread;public class Demo2 {public static void main(String[] args) {MyRunnable mr = new MyRunnable();        //4、创建Runnable的子类对象Thread t = new Thread(mr);                //5、将其当作参数传递给Thread的构造函数t.start();                                 //6、开启线程for(int i = 0; i < 1000; i++) {System.out.println("bb");}}
}class MyRunnable implements Runnable {            //1、定义一个类实现Runnable接口
    @Overridepublic void run() {                            //2、重写run方法、for (int i = 0; i < 1000; i++) {        //3、将要执行的代码写在run方法中System.out.println("ccccccccc");}}}

两种方式的区别:

查看源码的区别:

a、继承Thread:由于子类重写了Thread类的run(),当调用start()是,直接找子类的run()方法

b、实现Runnable:构造函数中传入了Runnable的引用,成员变量记住了它,start()调用run()方法时内部判断成员变量Runnable的引用是否为空,

不为空编译时看的是Runnable的run(),运行时执行的是子类的run()方法

继承Thread

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

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

实现Runnable接口

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

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

匿名内部类实现线程的两种方式:

继承Thread类

实现Runnable接口

package com.thread;public class Demo3 {public static void main(String[] args) {new Thread() {                                //1、继承Thread类public void run(){                        //2、重写run方法for (int i = 0; i < 1000; i++) {    //3、将要执行的代码写在run方法中System.out.println("aaaa");}}}.start();                                    //4、开启线程new Thread(new Runnable() {                    //1、将Runnable的子类对象传递给Thread的构造方法public void run() {                        //2、重写run方法for (int i = 0; i < 1000; i++) {    //3、将要执行的代码写在run方法中System.out.println("bbbbbb");}}}).start();                                    //4、开启线程
    }
}

获取名字和设置名字:

1、获取名字

通过getName()方法获取线程对象的名字

2、设置名字

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

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

package com.thread;public class Demo4 {public static void main(String[] args) {//demo1();Thread t1 = new Thread(){public void run(){//this.setName("张三");System.out.println(this.getName() + "....aaaaaa");}};Thread t2 = new Thread(){public void run(){//this.setName("李四");System.out.println(this.getName() + "....bbb");}};t1.setName("张三");t2.setName("李四");t1.start();t2.start();}public static void demo1() {new Thread("锋哥"){public void run(){System.out.println(this.getName() + "....aaaaaa");}}.start();new Thread("珊珊"){public void run(){System.out.println(this.getName() + "....bbb");}}.start();}
}

获取当前线程的对象:

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

package com.thread;public class Demo5 {public static void main(String[] args) {new Thread(){public void run(){System.out.println(getName() + "....aaaaa");}}.start();new Thread(new Runnable() {public void run() {//Thread.currentThread()获取当前正在执行的线程System.out.println(Thread.currentThread().getName() + "...bbb");}}).start();Thread.currentThread().setName("我是主线程");System.out.println(Thread.currentThread().getName());}
}

休眠线程:

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

package com.thread;public class Demo6 {public static void main(String[] args) throws InterruptedException {// demo1();new Thread() {public void run() {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(getName() + "....aaaaa");}}}.start();new Thread() {public void run() {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(getName() + "....bbbb");}}}.start();}public static void demo1() throws InterruptedException {for (int i = 20; i >= 0; i--) {Thread.sleep(1000);System.out.println("倒计时第" + i + "秒");}}}

守护线程:

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

package com.thread;public class Demo7 {public static void main(String[] args) {Thread t1 = new Thread(){public void run(){for (int i = 0; i < 2; i++) {System.out.println(getName() + "...aaaaaaa");}}};Thread t2 = new Thread(){public void run(){for (int i = 0; i < 50; i++) {System.out.println(getName() + "...bbb");}}};t2.setDaemon(true);                    //设置为守护线程
        t1.start();t2.start();}}

加入线程:

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

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

package com.thread;public class Demo8 {/*** join(),当前线程暂停,等待指定的线程执行结束后,当前线程再继续*/public static void main(String[] args) {Thread t1 = new Thread(){public void run(){for (int i = 0; i < 10; i++) {System.out.println(getName() + "...aaaaaaa");}}};Thread t2 = new Thread(){public void run(){for (int i = 0; i < 10; i++) {if (i == 2) {try {//t1.join();t1.join(1);                //插队指定的时间,过了指定时间后,两条线程交替执行} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(getName() + "...bbb");}}};t1.start();t2.start();}}

同步代码块:

1、什么情况下需要同步

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

如果两段代码是同步的,那么同一时间只能执行一段,在一段代码没执行结束之前,不会执行另外一段代码

2、同步代码块

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

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

package com.thread;public class Demo9 {public static void main(String[] args) {final Printer p = new Printer();new Thread() {public void run() {while (true) {p.print1();}}}.start();new Thread() {public void run() {while (true) {p.print2();}}}.start();}}class Printer {Demo d = new Demo();public void print1() {synchronized (d) {                    //同步代码块,锁机制,锁对象是任意的System.out.print("H");System.out.print("e");System.out.print("l");System.out.print("l");System.out.print("o");System.out.print("\r\n");}}public void print2() {                            //synchronized (new Demo()) {                    //锁对象不能用匿名对象,因为匿名对象不是同一个对象synchronized (d) {System.out.print("酷");System.out.print("狗");System.out.print("\r\n");}}}
class Demo{};

同步方法:

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

package com.thread;public class Demo10 {public static void main(String[] args) {final Printer2 p = new Printer2();new Thread() {public void run() {while (true) {p.print1();}}}.start();new Thread() {public void run() {while (true) {p.print2();}}}.start();}}class Printer2 {Demo d = new Demo();//非静态的同步方法的锁对象是神马?//非静态的同步方法的锁对象是this//静态的同步方法的锁对象是神马?//是该类的字节码对象public static synchronized void print1() {                        //同步方法只需要在方法上加synchronized关键字即可System.out.print("H");System.out.print("e");System.out.print("l");System.out.print("l");System.out.print("o");System.out.print("\r\n");}public void print2() {                            synchronized (Printer2.class) {System.out.print("酷");System.out.print("狗");System.out.print("\r\n");}}}

线程安全问题:

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

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

package com.thread;public class Demo11 {/*** 需求:铁路售票,一共100张,通过四个窗口卖完* @param args*/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;//private static Object obj = new Object();            //如果用引用数据类型成员变量当作锁对象,必须是静态的public void run(){while(true){synchronized (Ticket.class) {if (ticket <= 0) {break;}try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(getName() + "...这是第" + ticket-- + "号票");}}}
}

火车站卖票的例子用实现Runnable接口:

package com.thread;public class Demo12 {/*** 需求:火车站卖票的例子用实现Runnable接口* @param args*/public static void main(String[] args) {MyTicket mt = new MyTicket();new Thread(mt).start();new Thread(mt).start();new Thread(mt).start();new Thread(mt).start();/*Thread t1 = new Thread(mt);            //多次启动一个线程是非法的t1.start();t1.start();t1.start();t1.start();*/}}
class MyTicket implements Runnable {private int tickets = 100;@Overridepublic void run() {while(true){synchronized (this) {if (tickets <= 0) {break;}try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "...这是第" + tickets-- + "号票");}}}}

线程安全的类回顾:

看源码:Vector,StringBuffer,Hashtable,Collections.synchroinzed(xxx)

Vector是线程安全的,ArrayList是线程不安全的

StringBuffer是线程安全的,StringBuilder是线程不安全的

Hashtable是线程安全的,HashMap是线程不安全的

转载于:https://www.cnblogs.com/clqbolg/p/10974152.html

2019-06-02 Java学习日记之多线程上相关推荐

  1. 2019-06-03 Java学习日记 day24 多线程

    多线程 线程是程序执行的一台路径,一个进程中可以包含多条线程 多线程并发执行可以提高程序的效率,可以同时完成多项工作 多线程的应用背景 红蜘蛛同时共享屏幕给多个电脑 迅雷开启多条线程一起下载 QQ同时 ...

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

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

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

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

  4. 前端面试每日3+1(周汇总2019.06.02)

    周汇总 2019.06.02 <论语>,曾子曰:"吾日三省吾身"(我每天多次反省自己). 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯, ...

  5. Java学习日记-Day01

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

  6. 尚学堂Java学习日记Day3

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

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

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

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

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

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

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

最新文章

  1. 一位软件工程师的6年总结【转】
  2. 我这样理解技术人的成长过程
  3. 一个简单的因数分解java代码
  4. KubeCon 改为线上举办 | 云原生生态周报 Vol. 48
  5. 2440启动文件分析
  6. 用柠檬来发电真的可行吗?
  7. SSM框架的搭建学习(1)---MyBatis的环境搭建
  8. Chapter7-4_來自獵人暗黑大陸的模型 GPT-3
  9. Jetty9 源码初解(2)——IO之Connection
  10. python Image
  11. ant design入门学习笔记
  12. 分层聚类(Hierarchical clustering)
  13. 经过spring cloud gateway 网关访问nacos上的服务
  14. 2016/5/21 Seperate by *
  15. 优酷视频如何登录优酷账号?
  16. 解析移动互联网四大App云加固平台市场和质量对比
  17. Java子类与父类之间的对象转换
  18. 6.Servlet、JSP总结
  19. JVM之JVM面试题整理(长期更新)
  20. 深入理解Linux网络技术内幕学习笔记第十九章:因特网协议第四版(IPv4):Linux的原理和功能

热门文章

  1. 01背包、完全背包、多重背包问题的C++实现
  2. 趋势:“无人化”的未来,这些事情你需要知道!
  3. 权限控制_多租户系统设计之权限控制
  4. 漫步者蓝牙只有一边有声音_2019年上半年最具“诚意”的真无线劲挂蓝牙耳机新品...
  5. webtop搭建简单知识库粗略介绍
  6. web 端 gantt组件选型
  7. Crontab中文表达式解析
  8. Spring cloud Gateway(二) 一个Http请求的流程解析
  9. 聊聊零基础的我是如何学python的_零基础学python-4.3 对象的比较
  10. java中逗号分隔的字符串和List相互转换