测试类
package thead;
public class testThread {
public static void main(String [] arg){
Tickets ticket = new Tickets();
Thread t1 = new Thread(ticket,"窗口一:");
Thread t2 = new Thread(ticket,"窗口二:");
Thread t3 = new Thread(ticket,"窗口三:");
t1.start();
t2.start();
t3.start();
/* 注意:Thread中的start()方法是线程的就绪,而线程的启动,需要等待CPU的调度(也就是所谓的线程抢资源);
run()方法的方法体代表了线程需要完成的任务,称之为线程执行体。
void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
//即启动线程start方法会自动调用该类中重写的run方法
*/
/* 同步锁与资源共享:
CPU可能随机的在多个处于就绪状态中的线程中进行切换,这时就可能出现线程的安全问题;
线程安全问题,其实是指多线程环境下对共享资源的访问可能会引起此共享资源的不一致性,
而解决安全问题则需要同步锁的加入,执行synchronized部分代码的时候必须需要对象锁,
而一个对象只有一个锁,只有执行完synchronized里面的代码后释放锁,其他线程才可以获得锁,
那么就保证了同一时刻只有一个线程访问synchronized里面的代码。实现资源共享的关键是,
只有一个实例,synchronized使用的是同一把锁,用实例的锁或者定义一个实例。
这就需要使用实现Runnable接口的方式,实现多线程,这样传入的是一个实例。
继承Thread的方式,传入的是多个实例,每个实例都有一个锁,那就无法实现控制。
*/
}
}
实现了runnable接口的类
package thead;
public class Tickets implements Runnable{
// 为了让线程共享一个资源所以我们定义一个静态成员变量
private static int tickets = 100;
Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (Tickets.class) {
try {
if (tickets > 0) {
// Thread.sleep(100); 只是为了打印的效果,一行一行打印,如果不加则,所有结果一下子全都出来了
// getName:获取线程的名字,就是main方法里的第二个参数
System.out.println(Thread.currentThread().getName() + "正在售出第" + (tickets--) + "张票");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}