方式一:同步代码块
public class WindowsTest {
public static void main(String[] args) {
// SaleTicket s1 = new SaleTicket();
// Thread t1 = new Thread(s1);
// Thread t2 = new Thread(s1);
// Thread t3 = new Thread(s1);
// t1.start();
// t2.start();
// t3.start();
Window w1 = new Window();
Window w2 = new Window();
Window w3 = new Window();
w1.start();
w2.start();
w3.start();
}
}
//runnable
class SaleTicket implements Runnable{
int ticket = 100;
@Override
public void run(){
while(true)
{
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(this){
if(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+ticket);
ticket--;
}
else {
break;
}
}
}
}
}
//thread
class Window extends Thread{
static int ticket = 100;
@Override
public void run(){
while(true)
{
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(Window.class){
if(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+ticket);
ticket--;
}
else {
break;
}
}
}
}
}
方式二:同步方法
说明:如果操作共享数据的代码完整的声明在一个方法中,那么我们就可以将此方法声明为同步方法
public class WindowsTest1 {
public static void main(String[] args) {
SaleTicket s1 = new SaleTicket();
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s1);
Thread t3 = new Thread(s1);
t1.start();
t2.start();
t3.start();
// Window1 w1 = new Window1();
// Window1 w2 = new Window1();
// Window1 w3 = new Window1();
// w1.start();
// w2.start();
// w3.start();
}
}
//runnable
class SaleTicket1 implements Runnable{
int ticket = 100;
boolean isFlag = true;
@Override
public void run(){
while(isFlag)
{
show();
}
}
public synchronized void show(){
if(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+ticket);
ticket--;
}
else {
isFlag = false;
}
}
}
//thread
class Window1 extends Thread{
static int ticket = 100;
static boolean isFlag = true;
@Override
public void run(){
while(isFlag){
show();
}
}
//仅针对此问题,继承thread解决安全问题最好使用同步代码块
public static synchronized void show(){//默认同步监视器为this
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+ticket);
ticket--;
}
else {
isFlag = false;
}
}
}
synchronized好处:解决了线程的安全问题。
缺点:在操作共享数据时,多线程其实是串行执行的,意味着性能低。