2019-06-02 Java学习日记之多线程上
多线程程序实现的方式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学习日记之多线程上相关推荐
- 2019-06-03 Java学习日记 day24 多线程
多线程 线程是程序执行的一台路径,一个进程中可以包含多条线程 多线程并发执行可以提高程序的效率,可以同时完成多项工作 多线程的应用背景 红蜘蛛同时共享屏幕给多个电脑 迅雷开启多条线程一起下载 QQ同时 ...
- 2019-06-03 Java学习日记之多线程下GUI
多线程下 单例设计模式: 保证类在内存中只有一个对象 如何保证类在内存中只有一个对象呢? 1.控制类的创建,不让其他类来创建本类的对象 2.在本类中定义一个本类的对象,Singleton s 3.提供 ...
- Java学习日记1——基础认知
Java学习日记1--基础认知 学习Java阶段,如果发现不正确的描述,还请指正! 首先附上Java相关下载链接和配置教程链接 Java相关软件工具下载地址:官方下载 Java环境配置(win10配置 ...
- 前端面试每日3+1(周汇总2019.06.02)
周汇总 2019.06.02 <论语>,曾子曰:"吾日三省吾身"(我每天多次反省自己). 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯, ...
- Java学习日记-Day01
Java学习日记-Day01 Java语言概述 比特(byte)与字节 内存 Java基础知识图解 人机交互方式 常用的DOS命令 常用快捷键 计算机编程语言介绍 第一代语言 第二代语言 第三代语言 ...
- 尚学堂Java学习日记Day3
尚学堂Java学习日记Day3 第三天老师先回顾了昨天的内容我从回顾中掌握了新的知识 如下图所示 int与double计算,输出类型为double的不同结果 会把int转成double类型的,这是隐式 ...
- Java学习日记:UI篇(6)--谢尔宾斯基地毯图
Java学习日记:UI篇(6)–谢尔宾斯基地毯图 引言:谢尔宾斯基地毯是数学家谢尔宾斯基提出的一个分形图形,谢尔宾斯基地毯和谢尔宾斯基三角形基本类似,不同之处在于谢尔宾斯基地毯采用的是正方形进行分形构 ...
- 【日记】Java学习日记(第63天)持续无聊更新
前言 Youtube上EJ Media(up主)的视频我依次学完了HTML.CSS.Javascript.Jquery.觉得他教得挺好的(短小精悍),就继续学他教的JAVA.感觉EJ教的都是些语法什么 ...
- Java学习笔记5-1——多线程
目录 前言 核心概念 线程创建 继承Thread类 实现Runnable接口 上述两个方法小结 实现Callable接口 并发问题简介 静态代理模式 线程状态 线程停止(stop) 线程休眠(slee ...
最新文章
- 一位软件工程师的6年总结【转】
- 我这样理解技术人的成长过程
- 一个简单的因数分解java代码
- KubeCon 改为线上举办 | 云原生生态周报 Vol. 48
- 2440启动文件分析
- 用柠檬来发电真的可行吗?
- SSM框架的搭建学习(1)---MyBatis的环境搭建
- Chapter7-4_來自獵人暗黑大陸的模型 GPT-3
- Jetty9 源码初解(2)——IO之Connection
- python Image
- ant design入门学习笔记
- 分层聚类(Hierarchical clustering)
- 经过spring cloud gateway 网关访问nacos上的服务
- 2016/5/21 Seperate by *
- 优酷视频如何登录优酷账号?
- 解析移动互联网四大App云加固平台市场和质量对比
- Java子类与父类之间的对象转换
- 6.Servlet、JSP总结
- JVM之JVM面试题整理(长期更新)
- 深入理解Linux网络技术内幕学习笔记第十九章:因特网协议第四版(IPv4):Linux的原理和功能
热门文章
- 01背包、完全背包、多重背包问题的C++实现
- 趋势:“无人化”的未来,这些事情你需要知道!
- 权限控制_多租户系统设计之权限控制
- 漫步者蓝牙只有一边有声音_2019年上半年最具“诚意”的真无线劲挂蓝牙耳机新品...
- webtop搭建简单知识库粗略介绍
- web 端 gantt组件选型
- Crontab中文表达式解析
- Spring cloud Gateway(二) 一个Http请求的流程解析
- 聊聊零基础的我是如何学python的_零基础学python-4.3 对象的比较
- java中逗号分隔的字符串和List相互转换