package cn.mldn.juc.Ticket;
/**
* 高内聚低耦合的类
*/
class Ticket {
private int ticket = 30;
public synchronized void setTicket() {
//1、判断
while (ticket > 0) {
//2、卖票
ticket --;
System.out.println(Thread.currentThread().getName() + "线程卖出一张票" + ";剩余" + ticket + "张票");
}
}
}
/**
* 企业级多线程(题目,3个卖票员卖出30张票
* 1、在高内聚低耦合的前提下,线程 操作 资源类
* 2、
*/
public class TicketTest {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread thread = new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.setTicket();
}
},"线程A");
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.setTicket();
}
},"线程B");
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.setTicket();
}
},"线程C");
thread.start();
thread1.start();
thread2.start();
}
}
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 高内聚低耦合的类
*/
class Ticket {
private int ticket = 30;
private Lock lock = new ReentrantLock();
public void setTicket() {
lock.lock();
try {
//1、判断
if (ticket > 0) {
//2、卖票
ticket --;
System.out.println(Thread.currentThread().getName() + "线程卖出一张票" + ";剩余" + ticket + "张票");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
/**
* 企业级多线程(题目,3个卖票员卖出30张票
* 1、在高内聚低耦合的前提下,线程 操作 资源类
* 2、
*/
public class TicketTest {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread thread = new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.setTicket();
}
},"线程A");
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.setTicket();
}
},"线程B");
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.setTicket();
}
},"线程C");
thread.start();
thread1.start();
thread2.start();
}
}
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,//新建
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,//就绪状态
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,//阻塞状态
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
*
* - {@link Object#wait() Object.wait} with no timeout
* - {@link #join() Thread.join} with no timeout
* - {@link LockSupport#park() LockSupport.park}
*
*
* A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called Object.wait()
* on an object is waiting for another thread to call
* Object.notify() or Object.notifyAll() on
* that object. A thread that has called Thread.join()
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
*
* - {@link #sleep Thread.sleep}
* - {@link Object#wait(long) Object.wait} with timeout
* - {@link #join(long) Thread.join} with timeout
* - {@link LockSupport#parkNanos LockSupport.parkNanos}
* - {@link LockSupport#parkUntil LockSupport.parkUntil}
*
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
interface foo {
public void hello() ;
}
public class LambdaExpress {
public static void main(String[] args) {
foo foo = () -> {
System.out.println("hello");
};
foo.hello();
}
}
interface foo {
/*public void hello() ;*/
public int hello2(int a) ;
}
public class LambdaExpress {
public static void main(String[] args) {
foo foo = (int a) -> {
System.out.println("hello");
return a;
};
foo.hello2(1);
}
}
@FunctionalInterface
interface foo {
/*public void hello() ;*/
public int hello2(int a,int b) ;
}
public class LambdaExpress {
public static void main(String[] args) {
foo foo = (int a,int b) -> {
System.out.println("hello");
return a+b;
};
foo.hello2(1,2);
}
}
其实很简单,只有一个方法的接口就是函数式接口,此时就可以使用Lambda表达式。
生产者和消费者模型时线程间进行通信的原始模型,这个很重要,在很多地方都能应用起来的。
看第一种情况
public class ConsumerANDProduce {
//不管怎么样,一定要记住,涉及到了多线程,就会是线程操作资源类
public static void main(String[] args) {
AirConditioner airConditioner = new AirConditioner();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
airConditioner.increment();
}
},"线程A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
airConditioner.decrement();
}
},"线程B").start();
}
}
//资源类
class AirConditioner {
private int number = 0;
public synchronized void increment() {
//1、判断
if(number != 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2、干活
number++;
System.out.println("" + Thread.currentThread().getName() + "线程,完成生产");
//3、通知
this.notifyAll();
}
public synchronized void decrement() {
//1、判断
if(number == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2、干活
number--;
System.out.println("" + Thread.currentThread().getName() + "线程,完成消费");
//3、通知
this.notifyAll();
}
}
public synchronized void increment() {
//1、判断
while (number != 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2、干活
number++;
System.out.println("" + Thread.currentThread().getName() + "线程,完成生产" + number);
//3、通知
this.notifyAll();
}
public synchronized void decrement() {
//1、判断
while (number == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2、干活
number--;
System.out.println("" + Thread.currentThread().getName() + "线程,完成消费" + number);
//3、通知
this.notifyAll();
}
原理分析:当我们使用两个线程,一个去生成,一个去消费,此时number不管怎么样,一个生成,唤醒另外一个,此时不管怎么样都不会出现问题。但是当你多个线程的时候,就比如两个加线程A和B,两个减线程C和D,
假如如果A线程进去后,判断,如果被wait进行等待后,它在等待,当其他消费线程消费后,唤醒生产线程生产,如果两个生产线程都进行唤醒,哦豁了撒,两个线程都生产,不行(我们的目的是生成一个消费一个)。当用了while判断后,你判断了,如果下次被唤醒了,它要进行重新判断。这就是为什么能写while就防止虚假唤醒的原因了。
//资源类
class AirConditioner {
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void increment() {
lock.lock();
try {
//1、判断
while (number != 0) {
try {
condition.await();
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2、干活
number++;
System.out.println("" + Thread.currentThread().getName() + "线程,完成生产" + number);
//3、通知
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decrement() {
lock.lock();
try {
//1、判断
while (number == 0) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2、干活
number--;
System.out.println("" + Thread.currentThread().getName() + "线程,完成消费" + number);
//3、通知
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
class ShareResource {
int number = 1;
private Lock lock = new ReentrantLock();
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
private Condition conditionC = lock.newCondition();
private void AA() {
lock.lock();
try {
//1、判断
while (number != 1) {
conditionA.await();
}
//2、干活
for (int i = 0; i < 5; i++) {
System.out.println("AA线程打印");
}
//3、通知
number = 2;//设置标志位
conditionB.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
private void BB() {
lock.lock();
try {
//1、判断
while (number != 2) {
conditionA.await();
}
//2、干活
for (int i = 0; i < 10; i++) {
System.out.println("BB线程打印");
}
//3、通知
number = 3;//设置标志位
conditionC.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
private void CC() {
lock.lock();
try {
//1、判断
while (number != 3) {
conditionA.await();
}
//2、干活
for (int i = 0; i < 5; i++) {
System.out.println("CC线程打印");
}
//3、通知
number = 3;//设置标志位
conditionA.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
class Phone {
public synchronized void wangzry() throws Exception {
System.out.println("打开王者荣耀");
}
public synchronized void juedqs() throws Exception {
System.out.println("打开绝地求生");
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//1、资源类
Phone phone = new Phone();
new Thread(() -> {
try {
phone.wangzry();
} catch (Exception e) {
e.printStackTrace();
}
},"线程A").start();
Thread.sleep(1000);
new Thread(() -> {
try {
phone.juedqs();
} catch (Exception e) {
e.printStackTrace();
}
},"线程B").start();
}
}
并不是A和B同时进入到了资源类里面,线程启动并不是按着我们的意愿来启动的,底层用了native定义的。我们强制性的要求A线程先启动(因为B被停了),所以上面个方法肯定要先被启动。
class Phone {
public synchronized void wangzry() throws Exception {
Thread.sleep(4000);
System.out.println("打开王者荣耀");
}
public synchronized void juedqs() throws Exception {
System.out.println("打开绝地求生");
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//1、资源类
Phone phone = new Phone();
new Thread(() -> {
try {
phone.wangzry();
} catch (Exception e) {
e.printStackTrace();
}
},"线程A").start();
new Thread(() -> {
try {
phone.juedqs();
} catch (Exception e) {
e.printStackTrace();
}
},"线程B").start();
}
}
在方法上加了synchronized锁的是对象,即对象锁,同一时刻有且仅有一个线程能访问。
package cn.mldn.juc.cap;
class Phone {
public synchronized void wangzry() throws Exception {
Thread.sleep(4000);
System.out.println("打开王者荣耀");
}
public synchronized void juedqs() throws Exception {
System.out.println("打开绝地求生");
}
public void sayHello() throws Exception {
System.out.println("打开sayHello");
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//1、资源类
Phone phone = new Phone();
new Thread(() -> {
try {
phone.wangzry();
} catch (Exception e) {
e.printStackTrace();
}
},"线程A").start();
new Thread(() -> {
try {
phone.juedqs();
} catch (Exception e) {
e.printStackTrace();
}
},"线程B").start();
new Thread(() -> {
try {
phone.sayHello();
} catch (Exception e) {
e.printStackTrace();
}
},"线程C").start();
}
}
其实很好理解,普通方法(没有加上synchronized的方法),是不会和锁扯上关系的。
package cn.mldn.juc.cap;
class Phone {
public synchronized void wangzry() throws Exception {
Thread.sleep(4000);
System.out.println("打开王者荣耀");
}
public synchronized void juedqs() throws Exception {
System.out.println("打开绝地求生");
}
public void sayHello() throws Exception {
System.out.println("打开sayHello");
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//1、资源类
Phone phone = new Phone();
Phone phone1 = new Phone();
new Thread(() -> {
try {
phone.wangzry();
} catch (Exception e) {
e.printStackTrace();
}
},"线程A").start();
new Thread(() -> {
try {
phone1.juedqs();
} catch (Exception e) {
e.printStackTrace();
}
},"线程B").start();
}
}
他们之间没有任何竞争关系,不存在关系了。所以肯定是这个答案了。
class Phone {
public static synchronized void wangzry() throws Exception {
Thread.sleep(4000);
System.out.println("打开王者荣耀");
}
public static synchronized void juedqs() throws Exception {
System.out.println("打开绝地求生");
}
public void sayHello() throws Exception {
System.out.println("打开sayHello");
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//1、资源类
Phone phone = new Phone();
new Thread(() -> {
try {
phone.wangzry();
} catch (Exception e) {
e.printStackTrace();
}
},"线程A").start();
new Thread(() -> {
try {
phone.juedqs();
} catch (Exception e) {
e.printStackTrace();
}
},"线程B").start();
}
}
class Phone {
public static synchronized void wangzry() throws Exception {
Thread.sleep(4000);
System.out.println("打开王者荣耀");
}
public static synchronized void juedqs() throws Exception {
System.out.println("打开绝地求生");
}
public void sayHello() throws Exception {
System.out.println("打开sayHello");
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//1、资源类
Phone phone = new Phone();
Phone phone1 = new Phone();
new Thread(() -> {
try {
phone.wangzry();
} catch (Exception e) {
e.printStackTrace();
}
},"线程A").start();
Thread.sleep(1000);
new Thread(() -> {
try {
phone1.juedqs();
} catch (Exception e) {
e.printStackTrace();
}
},"线程B").start();
}
}
我们用static后,锁的不再是一个个的对象,而是锁的整个Phone.class类型。
package cn.mldn.juc.cap;
class Phone {
public static synchronized void wangzry() throws Exception {
Thread.sleep(4000);
System.out.println("打开王者荣耀");
}
public synchronized void juedqs() throws Exception {
System.out.println("打开绝地求生");
}
public void sayHello() throws Exception {
System.out.println("打开sayHello");
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//1、资源类
Phone phone = new Phone();
Phone phone1 = new Phone();
new Thread(() -> {
try {
phone.wangzry();
} catch (Exception e) {
e.printStackTrace();
}
},"线程A").start();
new Thread(() -> {
try {
phone.juedqs();
} catch (Exception e) {
e.printStackTrace();
}
},"线程B").start();
new Thread(() -> {
try {
phone.sayHello();
} catch (Exception e) {
e.printStackTrace();
}
},"线程C").start();
}
}
package cn.mldn.juc.cap;
class Phone {
public static synchronized void wangzry() throws Exception {
Thread.sleep(4000);
System.out.println("打开王者荣耀");
}
public synchronized void juedqs() throws Exception {
System.out.println("打开绝地求生");
}
public void sayHello() throws Exception {
System.out.println("打开sayHello");
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//1、资源类
Phone phone = new Phone();
Phone phone1 = new Phone();
new Thread(() -> {
try {
phone.wangzry();
} catch (Exception e) {
e.printStackTrace();
}
},"线程A").start();
new Thread(() -> {
try {
phone1.sayHello();
} catch (Exception e) {
e.printStackTrace();
}
},"线程C").start();
}
}
我们的两部手机,虽然你们是来自于同一个模板,但是我们两个间互相不影响。所以你该调调你的,不关我事。
比如我们的七个同血晚上下晚自习后,要离开教室,其中有一个人是班长,班长必须是最后一个把灯管了走。
public class test1 {
public static void main(String[] args) {
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "离开");
},"" + i).start();
}
System.out.println(Thread.currentThread().getName() + "班长离开");
}
}
public class test1 {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "离开");
countDownLatch.countDown();
},"" + i).start();
}
//班长要先卡着,只有上面的启动完了再走。
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "班长离开");
}
}
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(10,() -> {
System.out.println("集合完毕,可以开会");
});
for (int i = 0; i < 10; i++) {
int finalI = i;
new Thread(() -> {
System.out.println(String.valueOf(finalI) + "员工到会");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},i + "").start();
}
}
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);//模拟资源,有三个空车位
for (int i = 0; i < 6; i++) {
new Thread(() -> {
try {
semaphore.acquire();//占用空车位
System.out.println(Thread.currentThread().getName() + "线程,抢占到车位");
Thread.sleep(3);//占用3秒
System.out.println(Thread.currentThread().getName() + "线程,离开");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();//并且释放之前的空车位
}
},"" + i).start();
}
}
如果把资源设置为1,那就相当于使用synchronized。
class MyCache {
private volatile Map map = new HashMap<>();
public void put(String key,Object value) {
System.out.println("" + Thread.currentThread().getName() + "写入数据");
map.put(key,value);
System.out.println("" + Thread.currentThread().getName() + "写入成功");
}
public void get(String key) {
System.out.println("" + Thread.currentThread().getName() + "开始读取");
map.get(key);
System.out.println("" + Thread.currentThread().getName() + "读取成功");
}
}
class MyCache {
private volatile Map map = new HashMap<>();
public void put(String key,Object value) {
System.out.println("" + Thread.currentThread().getName() + "写入数据");
map.put(key,value);
System.out.println("" + Thread.currentThread().getName() + "写入成功");
}
public void get(String key) {
System.out.println("" + Thread.currentThread().getName() + "开始读取");
map.get(key);
System.out.println("" + Thread.currentThread().getName() + "读取成功");
}
}
public class test2 {
public static void main(String[] args) {
MyCache myCache = new MyCache();
//五个写
for (int i = 0; i < 5; i++) {
int finalI = i;
new Thread(() -> {
myCache.put("" + finalI, finalI+ "");
},finalI + "").start();
}
//五个读
for (int i = 0; i < 5; i++) {
int finalI = i;
new Thread(() -> {
myCache.get(finalI + "");
},finalI + "").start();
}
}
}
0写入数据
3写入数据
4写入数据
4写入成功
1写入数据
2写入数据
1写入成功
3写入成功
0写入成功
2写入成功
0开始读取
0读取成功
1开始读取
1读取成功
2开始读取
4开始读取
4读取成功
3开始读取
2读取成功
3读取成功
我们没法保证数据的完整性(即原子性)
class MyCache {
private volatile Map map = new HashMap<>();
private ReadWriteLock readWriteLock = null;
public void put(String key,Object value) {
readWriteLock.writeLock().lock();
try {
System.out.println("" + Thread.currentThread().getName() + "写入数据");
map.put(key,value);
System.out.println("" + Thread.currentThread().getName() + "写入成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
public void get(String key) {
readWriteLock.readLock().lock();
try {
System.out.println("" + Thread.currentThread().getName() + "开始读取");
map.get(key);
System.out.println("" + Thread.currentThread().getName() + "读取成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
可以比喻为海底捞火锅店的候客区。