Java超详细多线程入门教学

1. 同步代码块解决数据安全问题【应用】

  1. 1安全问题出现的条件
  • 是多线程环境
  • 有共享数据
  • 有多条语句操作共享数据

        1.2如何解决多线程安全问题呢?

  • 基本思想:让程序没有安全问题的环境

        2.3怎么实现呢?

  • 把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可。
  • Java提供了同步代码块synchronized的方式来解决。

        3.4同步代码块格式:

synchronized(任意对象) {

多条语句操作共享数据的代码

}

synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁

        4.5同步的好处和弊端

好处:解决了多线程的数据安全问题。

弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率

代码块同步代码展示:
package com.yexianglun;

public class SynchronizedTest implements Runnable {
    private int tickets = 100;

    //实列化一个obj对象
    private Object obj = new Object();

    @Override
    public void run() {
        //死循环
        while (true) {
            //解决代码块安全问题
            synchronized (obj) {
                //可自加代码休眠 Thread.sleep(100)(100毫秒)
                if (tickets <= 0) {
                    System.out.println(Thread.currentThread().getName() + "票卖完了");
                    break;
                }
                System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                tickets--;
                System.out.println("还剩" + tickets + "张票");
            }
        }
    }
}

2.同步方法解决数据安全问题【应用】

        2.1同步方法的格式

同步方法:就是把synchronized关键字加到方法上。

修饰符 synchronized 返回值类型 方法名(方法参数) {

方法体;

}

        2.2同步方法的锁对象是什么呢?

this

        2.3静态同步方法

同步静态方法:就是把synchronized关键字加到静态方法上。

修饰符 static synchronized 返回值类型 方法名(方法参数) {

方法体;

        2.4同步静态方法的锁对象是什么呢?

类名.class

静态同步代码展示:
public class MyRunnable implements Runnable {

    private static int ticketCount = 100;

    @Override
    public void run() {
        while (true) {
            if ("窗口一".equals(Thread.currentThread().getName())) {
//同步方法 
                boolean result = synchronizedMthod();
                if (result) {
                    break;
                }
            }

            if ("窗口二".equals(Thread.currentThread().getName())) {
//同步代码块 
                synchronized (MyRunnable.class) {
                    if (ticketCount == 0) {
                        break;
                    } else {
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        ticketCount‐‐;
                        System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticketCount + "张票");
                    }
                }
            }
        }
    }

    private static synchronized boolean synchronizedMthod() {
        if (ticketCount == 0) {
            return true;
        } else {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticketCount‐‐;
            System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticketCount + "张票");
            return false;
        }
    }
} 
方法同步代码展示:
package com.yexianglun;

public class SynchronizedMethodTest implements Runnable {
    private int tickets = 0;

    @Override
    public void run() {
        while (true) {
            boolean b = syn();
            if (!b) {
                break;
            }
        }
    }

    //方法同步
    public synchronized boolean syn() {
        //没票情况下
        if (tickets == 100) {
            System.out.println(Thread.currentThread().getName() + "售罄");
            return false;//没票了
        }
        tickets++;
        System.out.println(Thread.currentThread().getName() + "出售第" + tickets + "票");

//        System.out.println("还剩" + (tickets + 1) + "张票");

        return true;
    }
}

代码测试展示

package com.yexianglun;

public class Test {
    public static void main(String[] args) {

        //1.使用同代码块同步

//        //实列化一个SynchronizedTest类对象
//        SynchronizedTest syn = new SynchronizedTest();
//
//        //实列化三个窗口对象(线程)
//        Thread thread1 = new Thread(syn, "一号窗口");
//        Thread thread2 = new Thread(syn, "二号窗口");
//        Thread thread3 = new Thread(syn, "三号窗口");
//
//        thread1.start();
//        thread2.start();
//        thread3.start();


        //2.使用方法同步
//        SynchronizedMethodTest sm = new SynchronizedMethodTest();
//
//        Thread thread1 = new Thread(sm, "一号窗口");
//        Thread thread2 = new Thread(sm, "二号窗口");
//        Thread thread3 = new Thread(sm, "三号窗口");
//
//        thread1.start();
//        thread2.start();
//        thread3.start();

        //使用Lock锁
        LockTest lockTest = new LockTest();
        Thread thread1 = new Thread(lockTest, "一号窗口");
        Thread thread2 = new Thread(lockTest, "二号窗口");
        Thread thread3 = new Thread(lockTest, "三号窗口");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

 

        3.Lock锁【应用】

虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock。

Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化。

        3.1ReentrantLock构造方法

方法名

说明

ReentrantLock() 

创建一个ReentrantLock的实例。

        3.2加锁解锁方法

方法名

说明

void lock()

获得锁。

void unlock()

释放锁。

Lock锁代码展示:
package com.yexianglun;

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

public class LockTest implements Runnable {
    private Lock lock = new ReentrantLock();
    private int ticket = 0;

    @Override
    public void run() {
        while (true) {
            try {
                lock.lock();
                if (ticket >= 100) {
                    //卖完
                    System.out.println("以售完");
                    break;
                } else {
                    Thread.sleep(10);
                    ticket++;
                    System.out.println(Thread.currentThread().getName() + "出售" + ticket + "张");
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }
    }
}

测试代码同上

        ​​​​​​​4.死锁【理解】

  1. 概述

线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。

  1. 什么情况下会产生死锁
  1. 资源有限
  2. 同步嵌套
死锁代码展示:​​​​​​​
public class Demo {
    public static void main(String[] args) {

        Object objA = new Object();
        Object objB = new Object();

        new Thread(()‐ > {
        while (true) {
            synchronized (objA) {
//线程一 
                synchronized (objB) {
                    System.out.println("小康同学正在走路");
                }
            }
        } 
}).start();

        new Thread(()‐ > {
        while (true) {
            synchronized (objB) {
//线程二 
                synchronized (objA) {
                    System.out.println("小薇同学正在走路");
                }
            }
        } 
}).start();
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值