Java 多线程(2)

线程安全

多线程访问了共享的数据,会产生线程安全问题

在下面的代码中出现了两个窗口卖同一张票,和票数出现负数的问题

加入sleep是为了提高安全问题出现的概率,不加也可,增加票数也可 

package ThreadGoOn;

public class ThreadTicket implements Runnable {
    private int ticketCnt = 10;
    @Override
    public void run() {
        while (true){
            if(ticketCnt>0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在卖第"+ticketCnt+"张票");
                ticketCnt--;
            }/*else {
                break;
            }*/
        }
    }
}
package ThreadGoOn;

public class TestMain {
    public static void main(String[] args) {
        // 创建接口的实现类对象
        ThreadTicket threadTicket = new ThreadTicket();
        new Thread(threadTicket).start();
        new Thread(threadTicket).start();
        new Thread(threadTicket).start();
    }
}

线程安全问题出现的原理

解决线程安全问题

方法一同步代码块

注意锁对象是同一个,所以不能将Object创建在run方法内

package ThreadDemo1127.Demo01;
/**
 * @Auther  hangsir
 */

public class RunnableImpl implements Runnable{
    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (obj){
                if(ticket>0){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket);
                    ticket--;
                }
            }
        }
    }
}
package ThreadDemo1127.Demo01;

public class Main {
    public static void main(String[] args) {
        RunnableImpl run = new RunnableImpl();
        new Thread(run).start();
        new Thread(run).start();
        new Thread(run).start();
    }
}

 同步技术的原理

方法二同步方法

package ThreadDemo1127.Demo01;
/**
 * @Auther  hangsir
 */

public class RunnableImpl implements Runnable{
    private int ticket = 100;
    @Override
    public void run() {
        while (true){
            sellTicket();
        }
    }
    public synchronized void sellTicket(){
        if(ticket>0){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket);
            ticket--;
        }
    }
}

方法三Lock锁


使用

package ThreadDemo1127.Demo01;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Auther  hangsir
 */

public class RunnableImpl implements Runnable{
    private int ticket = 100;
    Lock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true){
            lock.lock();
            if(ticket>0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket);
                ticket--;
            }
            lock.unlock();
        }
    }
}

finally优化,不管程序时候出现异常,都会释放锁

线程状态

等待唤醒案例(生产者消费者模型)

代码实现

消费者线程

下面的代码加在wait后面

再加上一条华丽的分割线

生产者线程

将两个线程中的run方法中的内容设置成while死循环,顾客一直等着买包子。

wait带参方法和notifyAll方法

只使用notify,如果有多个线程,会随机唤醒一个消费者线程。使用notifyAll方法可以唤醒所有的消费者线程。

线程间通信

等待唤醒机制概述

分析与代码实现

代码实现

线程池

原理

好处

使用

代码实现

Runnable接口的实现类

package ThreadGoOn;

public class RunnableImpl implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"创建了一个新的线程执行!");
    }
}
package ThreadGoOn;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPool {
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(2);
        es.submit(new RunnableImpl());
        es.submit(new RunnableImpl());
        es.submit(new RunnableImpl());
        es.submit(new RunnableImpl());
        es.submit(new RunnableImpl());
        es.shutdown();
    }
}
发布了369 篇原创文章 · 获赞 74 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_41333844/article/details/102966694