1,,多个窗口一起买1000张票,出现线程安全问题--------解决方法:同步
public class f1Tickets {
public static void main(String[] args) {
// TODO Auto-generated method stub
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
}
}
class tickets extends Thread{//以后开发 必须使用Runnable创建线程
static int totals = 100;//当static 不存在的时候不会出现安全问题 因为没有操作共享数据
public void run(){
while (true) {
if(totals>0){
//需要让线程等待一下才容易看到效果
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"票还剩下:。。"+totals--);
}
}
}
}
/*
* Thread-6票还剩下:。。3
Thread-4票还剩下:。。2
Thread-5票还剩下:。。1
Thread-0票还剩下:。。0
Thread-1票还剩下:。。-1
Thread-3票还剩下:。。-2
Thread-6票还剩下:。。-3
Thread-2票还剩下:。。-4
Thread-4票还剩下:。。-5
*
* */
解决办法 同步
public class f1Tickets {
public static void main(String[] args) {
// TODO Auto-generated method stub
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
new tickets().start();
}
}
class tickets extends Thread{
static int totals = 100;//当static 不存在的时候不会出现安全问题 因为没有操作共享数据
public void run(){
while (true) {
synchronized (tickets.class) {//同步的重要前提是 多线程操作共享数据,多线程同一把锁
if(totals>0){
//需要让线程等待一下才容易看到效果
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"票还剩下:。。"+totals--);
}
}
}
}
}
2,性别错位问题引出——等待唤醒机制
出现问题:性别张冠李戴
public class f1WaitAndSingle {
public static void main(String[] args) {
new Thread(new Set()).start();
new Thread(new Out()).start();
}
}
class Info{
String name ;
String sex;
private static Info info = new Info();
public static Info getInstance(){
return info;
}
public void sop(){
System.out.println(name+",,,,,"+sex);
}
}
class Set implements Runnable{
@Override
public void run() {
Info info = Info.getInstance();
int x = 1;
while (true) {
if (x==1) {
info.name = "百里屠苏:---";
info.sex = "man";
} else {
info.name = "风晴雪:---";
info.sex = "女生";
}
// x = (x+1)%2;
x = x^2;
}
}
}
class Out implements Runnable{
public void run() {
Info info = Info.getInstance();
while (true) {
info.sop();
}
}
}
/*出问题的原因:当设置线程只设置好姓名而没设置好性别的时候 执行权被输出线程抢走
* 输出线程输出当前设置好的名字和上一次设置的性别 导致问题的产生
* 百里屠苏:---,,,,,man
百里屠苏:---,,,,,man
风晴雪:---,,,,,女生
百里屠苏:---,,,,,女生
风晴雪:---,,,,,man
风晴雪:---,,,,,女生
百里屠苏:---,,,,,女生
风晴雪:---,,,,,女生
* */
解决方法:等待唤醒机制
public class f2WaitAndSingle {
public static void main(String[] args) {
new Thread(new Set2()).start();
new Thread(new Out2()).start();
}
}
class Info2{
String name ;
String sex;
boolean flag;
private static Info2 info = new Info2();
public static Info2 getInstance(){
return info;
}
public void sop(){
System.out.println(name+",,,,,"+sex);
}
}
//解决问题的办法 1:先设置好人和性别 然后输出 建立一个标记表明设置好了 和输出好了
// class Set2 implements Runnable{
// @Override
// public void run() {
// Info2 info = Info2.getInstance();
// int x = 1;
// while (true) {
// if(!info.flag){
// if (x==1) {
// info.name = "百里屠苏:---";
// info.sex = "man";
// } else {
// info.name = "风晴雪:---";
// info.sex = "女生";
// }
x = (x+1)%2;
// x = x^2;
// info.flag = true;
// }
// }
// }
// }
// class Out2 implements Runnable{
// public void run() {
// Info2 info = Info2.getInstance();
// while (true) {
// if(info.flag){
// info.sop();
// info.flag = false;
// }
// }
// }
// }
// 解决问题的方式2,等待唤醒机制
class Set2 implements Runnable{
@Override
public void run() {
Info2 info = Info2.getInstance();
int x = 1;
while (true) {
synchronized (info) {
if(!info.flag)
try {
info.wait();
} catch (Exception e) {
e.printStackTrace();
}
if (x==1) {
info.name = "百里屠苏:---";
info.sex = "man";
} else {
info.name = "风晴雪:---";
info.sex = "女生";
}
// x = (x+1)%2;
x = x^2;
info.flag = false;//让本线程下一次进入wait等待状态
info.notify();//唤醒info所监视的一个线程 此时就是 正在等待状态的 Out2线程
}
}
}
}
class Out2 implements Runnable{
public void run() {
Info2 info = Info2.getInstance();
while (true) {
synchronized (info) {
if(info.flag)//该if语句的方法体是 wait
try {
info.wait();
} catch (Exception e) {
e.printStackTrace();
}
info.sop();
info.flag = true;//让本线程下一次进入wait等待状态
info.notify();//唤醒info所监视的一个线程 此时就是 正在等待状态的 Set2线程
}
}
}
}
单生产者与单消费者:保证线程安全 使用新锁实现
public class f1ProducterAndConsumer {
public static void main(String[] args) {
new Thread(new Productor(),"生产者").start();
new Thread(new Consumer(),"消费者").start();
// new Thread(new Productor(),"生产者2").start();
// new Thread(new Consumer(),"消费者2").start();
//当出现多生产者多消费者的时候会出现 生产一个商品被消费两次 或者生产两个商品只有一个被消费
}
}
class Reso{
int count;
boolean flag;
private static Reso res = new Reso();
public static Reso getReso(){
return res;
}
Lock lock = new ReentrantLock();
Condition conP = lock.newCondition();
Condition conS = lock.newCondition();
public void produce(){
while (true) {
lock.lock();
if (!res.flag)
try {
conP.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
res.count++;
System.out.println(Thread.currentThread().getName()+"生产一个商品:"+res.count);
res.flag = false;
conS.signal();
}
}
public void consum(){
while (true) {
lock.lock();
if (res.flag)
try {
conS.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"xiaofei一个商品:"+res.count);
res.flag = true;
conP.signal();
}
}
}
class Productor implements Runnable{
public void run() {
Reso res = Reso.getReso();
res.produce();
}
}
class Consumer implements Runnable{
@Override
public void run() {
Reso res = Reso.getReso();
res.consum();
}
}
多生产者与多消费者:保证线程安全 使用新锁实现
public class f1ProductorsAndConsumers {
public static void main(String[] args) {
new Thread(new Productors(),"生产者").start();
new Thread(new Consumers(),"消费者").start();
new Thread(new Productors(),"生产者2").start();
new Thread(new Consumers(),"消费者2").start();
new Thread(new Productors()).start();
new Thread(new Consumers()).start();
new Thread(new Productors()).start();
new Thread(new Consumers()).start();
new Thread(new Productors()).start();
new Thread(new Consumers()).start();
new Thread(new Productors()).start();
new Thread(new Consumers()).start();
new Thread(new Productors()).start();
new Thread(new Consumers()).start();
//当出现多生产者多消费者的时候会出现 生产一个商品被消费两次 或者生产两个商品只有一个被消费
}
}
class Resource2{
int count;
boolean flag;
private static Resource2 res = new Resource2();
public static Resource2 getInstance(){
return res;
}
Lock lock = new ReentrantLock();
Condition conP = lock.newCondition();
Condition conS = lock.newCondition();
public void product(){
while (true) {
lock.lock();
while (!flag)//因为不知一个线程会执行这代码 多个线程等待 因为可能有一个线程把标记给改了
try {
conP.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
System.out.println(Thread.currentThread().getName()+"生产一个商品:"+res.count);
flag = false;
conS.signal();
}
}
public void consume(){
while (true) {
lock.lock();
if(flag)
try {
conS.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"xiaofei一个商品:"+res.count);
res.flag = true;
conP.signal();
}
}
}
class Productors implements Runnable{
public void run() {
Resource2 res = Resource2.getInstance();
res.product();
}
}
class Consumers implements Runnable{
public void run() {
Resource2 res = Resource2.getInstance();
res.consume();
}
}