第一种 继承extends Thread
第二种 接口implements Runnable
总结:多个线程一起占用即使设置了静态变量100还是没有用,比如三个线程这时候一起用100,很好大家都获得100,然后大家都输出100,然后线程一睡觉了,但是线程二,醒的很快,然后线程二获得99,然后减1得98.突然线程一线程三刚好又一起行来拿到98。如果让他们有序获得,就上一个锁,大家先到也得排着等待处理。
线程的同步可以举很多的例子,比如说你去看电影的时候上网买电影票,你选择一个座位的电影票的时候,那边线下的人就不能买了,因为线程同步的原因。如果线程不同步,我们都知道网络都会有延迟的,比如线下的人到电影院买电影票了,你也在网上买一张电影票,到时候大家都尴尬了哈哈哈。再举个生活的例子比如上厕所你就焕然大悟了!!最后将带你去深入理解怎么设置线程安全,也就是去厕所怎么上锁。
解析这段代码,当t1和t2两个线程一起走的时候,t1这边100先-1 等于99 然后t1睡觉,t2也运行。99减1。当t1和t2睡醒的时候发现数值就是98。
代码
package com.xiancheng.ch01;
public class SynchoTest1 extends Thread {
//定义了静态方法 其里面的也是静态
static MyClass c1 = new MyClass();
public void run() {
c1.showCount();
}
public static void main(String[] args) {
SynchoTest1 t1 =new SynchoTest1();
SynchoTest1 t2 =new SynchoTest1();
t2.start();
t1.start();
}
}
class MyClass{
int count =100;
public synchronized void showCount() {
//进来先减1
count --;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("count :"+count);
}
}
第一种:同步代码块
代码:
package com.xiancheng.ch01;
public class SynchoTest603 {
public static void main(String[] args) {
//创建三个窗口卖票,总票数100
Window604 w1 =new Window604("售票窗口1");
Window604 w2 =new Window604("售票窗口2");
Window604 w3 =new Window604("售票窗口3");
w1.start();
w2.start();
w3.start();
}
}
class Window604 extends Thread{
//重写run方法
//共享数据静态池
static int ticket =100;
public Window604(String name) {
super(name);
}
public void run() {
while(true) {
showTicket();
if(ticket<=0) {
break;
}
}
}
//线程安全的静态方法 同一时刻只能接收
// 方法加同步,同一时刻,只能接收一个线程的访问
private static synchronized void showTicket() {
if(ticket<=0) {
return;
}
System.out.println(Thread.currentThread().getName()+"卖出第"+ticket);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ticket --;
}
}
第二种 同步监视器里面的字节码文件
package com.xiancheng.ch01;
public class SynchoTest2 {
public static void main(String[] args) {
Window3 w1 =new Window3();
Thread thread1 = new Thread(w1);
Thread thread2 = new Thread(w1);
Thread thread3 = new Thread(w1);
thread1.setName("窗口1");
thread2.setName("窗口2");
thread3.setName("窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class Window3 implements Runnable{
int ticket =100;
public void run() {
while(true) {
//同步监视器(锁) 必须是多个线程共有的数据
//这个类生成的字节码文件.class也是只有一份。
synchronized (Window3.class) {
if(ticket>0) {
System.out.println(Thread.currentThread().getName()+"卖出第"+ticket);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
ticket --;
}else {
break;
}
}
}
}
}
第三种:同步监视器同一个类(适用于继承接口的类)
代码
package com.xiancheng.ch01;
public class SynchoTest602 {
public static void main(String[] args) {
Window602 w1 =new Window602();
Thread thread1 = new Thread(w1);
Thread thread2 = new Thread(w1);
Thread thread3 = new Thread(w1);
thread1.setName("窗口1");
thread2.setName("窗口2");
thread3.setName("窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class Window602 implements Runnable{
int ticket =100;
public void run() {
while(true) {
//同步监视器(锁) 必须是多个线程共有的数据
//上面实例就一个
synchronized (this) {
if(ticket>0) {
System.out.println(Thread.currentThread().getName()+"卖出第"+ticket);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
ticket --;
}else {
break;
}
}
}
}
}