黑马程序员—Java基础学习笔记之多线程

本文详细介绍了Java中线程的基本概念与应用场景,并通过具体示例讲解了如何使用继承Thread类与实现Runnable接口的方式创建多线程。此外,还探讨了同步代码块的使用及其在解决多线程安全问题中的作用。
摘要由CSDN通过智能技术生成

-----------android培训java培训java学习型技术博客、期待与您交流!-----------

.线程的概念

1.什么是线程

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

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

2.多线程的应用场景(现实实例)

网络教室:红蜘蛛,同时共享屏幕给多个电脑

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

QQ同时和多个人一起视频

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

.两种方式开启新线程

1.继承Thread

定义类继承Thread

重写run方法

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

创建线程对象

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

举例:多窗口卖票

package com.biji;
//创建Ticket类 继承Thread
class Ticket1 extends Thread {
	private static int tick = 100;//tick设置为static,共享
	public void run() {//重写run方法
		while(true) {
			if(tick>0) {//currentThread继承于Thread,调用父类的getName()
				System.out.println(currentThread().getName()+"sale:"+tick--);
			}
		}
	}
}
public class Thread1 {

	public static void main(String[] args) {
		Ticket1 t1 = new Ticket1();//创建线程对象
		Ticket1 t2 = new Ticket1();//创建线程对象
		Ticket1 t3 = new Ticket1();//创建线程对象
		
		t1.start();//开启线程
		t2.start();//开启线程
		t3.start();//开启线程

	}

}

2.实现Runnable

定义类实现Runnable接口

实现run方法

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

创建自定义的Runnable对象

创建Thread对象,传入Runnable

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

package com.biji;
/*
 	需求:多窗口卖票
 */
/*  
 	分析:创建线程的第二种方式:实现Runnable接口
  	步骤:1,定义类实现Runnable接口
  		2,覆盖Runnable接口中的run方法
  		3,通过Thread类建立线程对象
  		4,将Runnable接口的子类对象做为参数传递给Thread类的构造函数
  		5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法
 */
class Ticket implements Runnable {
	private int ticket = 100;
	public void run() {
		while(true) {
			if(ticket>0) {
				System.out.println(Thread.currentThread().getName()+"...sale:"+ticket--);
			}
		}
	}
}

public class SalesTicket {
	public static void main(String[] args) {
		Ticket t = new Ticket();
		Thread t1 = new Thread(t);//创建一个线程,将t做为参数传递给Thread
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		
	}

}

3.两种方式的区别

区别一:

a.由于子类重写了Thread类的run(),当调用start(),直接找子类的run()方法

b.构造函数中传入了Runnable的引用,成员变量记住了它, start()调用run()方法时内部判断成员变量Runnable是否为空,不为空则执行Runnablerun()

区别二:

a.继承Thread只能是单继承,如果自己定义的线程类已经有了父类,就不能再继承了

b.实现Runnable接口可以多实现,即使自己定义线程类已经有父类可以实现Runnable接口

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

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

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

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

三.同步代码块

1.什么情况下需要同步

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

如果两段代码是同步的,那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码,这样就可以避免出现多线程不安全问题.

注意:安全问题出现原因---当多条语句在操作同一个线程的共享数据时(比如多个窗口在卖火车票),一个线程对多条语句只执行了一部分还没执行完,另一个线程参与进来执行,导致共享的数据错误.

2,同步代码块格式:

synchronized(对象){

需要同步的代码

}

3.同步前提:1,需要两个或以上的线程

2,多个线程使用的是同一个锁

同步的弊端:多个线程同步时候,每个线程都会判断同步上的锁,耗费资源,降低运行效率

举例:还是多窗口卖票实例

package com.biji;
class Tickets implements Runnable {
	private int ticket = 100;
	Object obj = new Object();//创建根类Object对象
	public void run() {
		while(true) {
			synchronized (obj) {
				if(ticket>0) {
					try{
						Thread.sleep(1);//在这里让线程休眠1毫秒
					}catch(Exception e){}
					System.out.println(Thread.currentThread().getName()+"...sale:"+ticket--);
				}
			}
		}
	}
}

public class Synchronized {
	public static void main(String[] args) {
		Tickets t = new Tickets();
		Thread t1 = new Thread(t);//创建一个线程,将t做为参数传递给Thread
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		
	}

}

运行结果:

Thread-0...sale:100
Thread-0...sale:99
Thread-0...sale:98
Thread-0...sale:97
Thread-2...sale:96
Thread-2...sale:95
Thread-1...sale:94
Thread-1...sale:93
Thread-1...sale:92
Thread-1...sale:91
Thread-1...sale:90
Thread-1...sale:89
Thread-1...sale:88
Thread-1...sale:87
Thread-1...sale:86
Thread-1...sale:85
Thread-1...sale:84
Thread-1...sale:83
Thread-1...sale:82
Thread-1...sale:81
Thread-1...sale:80
Thread-1...sale:79
Thread-1...sale:78
Thread-1...sale:77
Thread-1...sale:76
Thread-1...sale:75
Thread-1...sale:74
Thread-1...sale:73
Thread-1...sale:72
Thread-1...sale:71
Thread-1...sale:70
Thread-1...sale:69
Thread-1...sale:68
Thread-1...sale:67
Thread-1...sale:66
Thread-1...sale:65
Thread-1...sale:64
Thread-1...sale:63
Thread-1...sale:62
Thread-1...sale:61
Thread-1...sale:60
Thread-1...sale:59
Thread-1...sale:58
Thread-1...sale:57
Thread-1...sale:56
Thread-1...sale:55
Thread-1...sale:54
Thread-1...sale:53
Thread-1...sale:52
Thread-1...sale:51
Thread-1...sale:50
Thread-1...sale:49
Thread-1...sale:48
Thread-1...sale:47
Thread-1...sale:46
Thread-1...sale:45
Thread-1...sale:44
Thread-1...sale:43
Thread-1...sale:42
Thread-1...sale:41
Thread-1...sale:40
Thread-1...sale:39
Thread-1...sale:38
Thread-1...sale:37
Thread-1...sale:36
Thread-1...sale:35
Thread-1...sale:34
Thread-1...sale:33
Thread-1...sale:32
Thread-1...sale:31
Thread-1...sale:30
Thread-1...sale:29
Thread-1...sale:28
Thread-1...sale:27
Thread-1...sale:26
Thread-1...sale:25
Thread-1...sale:24
Thread-1...sale:23
Thread-1...sale:22
Thread-1...sale:21
Thread-1...sale:20
Thread-1...sale:19
Thread-1...sale:18
Thread-1...sale:17
Thread-1...sale:16
Thread-1...sale:15
Thread-1...sale:14
Thread-1...sale:13
Thread-1...sale:12
Thread-1...sale:11
Thread-1...sale:10
Thread-1...sale:9
Thread-1...sale:8
Thread-1...sale:7
Thread-1...sale:6
Thread-1...sale:5
Thread-1...sale:4
Thread-1...sale:3
Thread-1...sale:2
Thread-1...sale:1



-----------android培训java培训java学习型技术博客、期待与您交流!-----------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值