sleep方法需要指定睡眠时间,单位是毫秒。
定义类实现Runnable接口
覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。
通过Thread类创建线程
将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
因为,自定义的run方法所属的对象是Runnable接口的子类对象。
所以要让线程去指定指定对象的run方法,就必须明确该run方法所属对象。
public Thread(Runnable target)
分配新的 Thread 对象。这种构造方法与 Thread(null, target, gname ) 具有相同的作用,其中的 gname 是一个新生成的名称。自动生成的名称的形式为 “Thread-”+ n,其中的 n 为整数。
**参数:**target - 其 run 方法被调用的对象。
另请参见:
调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
6.
实现方式好处:避免单继承的局限性。在定义线程时,建议使用实现方式。
两种方式区别:
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable:线程代码存在接口的子类的run方法。
运行发现,可能会打印出0,-1,-2等错票。多线程的运行出现了安全问题。
原因:
多个线程访问出现延迟。
线程随机性。
(当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。)
注:线程安全问题在理想状态下,不容易出现,但一旦出现对软件的影响是非常大的。
解决办法:对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
Java对于多线程的安全问题提供了的解决方式,即同步代码块。java多线程死锁(synchronized)
格式:
synchronized(对象) {
需要被同步的代码 //运行到共享数据的代码
}
同步可以解决安全问题的根本原因就在那个对象上,该对象如同锁的功能。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权也进不去,因为没有获取锁。(eg.火车上的卫生间-有人就锁门,其它人进不来)
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
未满足这两个条件,不能称其为同步。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题
弊端:多个线程需要判断锁,较为消耗资源(当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。)
public class Ticket implements Runnable//extends Thread
{
private int tick = 100;
Object obj = new Object();//通过Object创建锁对象
public void run() {
while (true) {
synchronized (obj) {//同步,防止线程安全问题
if (tick > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
}
//在没Synchronized的情况下用sleep方法人为让线程停在这儿,验证是否会像下面这样出现安全问题
//如没Synchronized,可能在tick=1时,多个线程判断完停在这儿,再轮到它们运行时导致共享数据tick运行结果出现负数(tick=1 tick=0 tick=-1…),即出现线程安全问题
System.out.println(Thread.currentThread().getName() + "....sale : " + tick--);
}
}
}
}
}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-55883-2.html
从去年开始不再喝了
放个屁都有道理