目录
/** * 题目:三个窗口售票,总票数100张,售完为止 * * 出现线程安全解决方式: * 方式一: * 1、同步代码块; * synchronized(同步代码块){ * //需要被同步的代码 * } * 说明:1、操作共享数据的代码,即为需要被同步的代码 * 2、共享数据:多个线程共同操作的变量,比如:ticket就是共享数据。 * 3、同步监视器,俗称:锁。任何一个类都可以充当一把锁。 * 要求:多个线程必须用同意把锁 * * 2、this * synchronized(this){ //this表示当前对象,且当前对象只有一个 * * } * 3、当前类.class充当,类只会加载一次 * synchronized(当前类.class){ * * } * * 方式二:同步方法 * 如果操作共享数据的代码完整的声明在一个方法中国,我们不妨将此方法声明同步的 * 同步代码块总结: * 1、同步方法仍涉及到同步监控器,只是不愿要我们显示声明 * 2、非静态的同步方式,同步监控器是:this * 静态的同步方式,同步监控器是当前类本身 * * *使用同步机制将单例模式中的懒汉式更改为线程安全的 * * * 解决线程问题的方式三:Lock锁-----JDK5.0新增 * 1、实例化lock * 2、调用锁定方法lock() * 3、调用解锁方法:unlock() */
- /*
- * 出现线程安全解决方式:
- * 方式一:
- * 1、同步代码块;
- * synchronized(同步代码块){
- * //需要被同步的代码
- * }
- */
-
-
- class window1 implements Runnable{
- private int ticket = 100;
- Object obj = new Object();
- @Override
- public void run() {
- while(true){
- // 这里也可以使用this,需要把obj的创建对象删除,在把synchronized()括号里替换成this
- synchronized(obj) {
- if (ticket > 0) {
- // 出现线程安全
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "卖票,剩余票数:" + ticket);
- ticket--;
- } else {
- break;
- }
- }
- }
- }
- }
-
- public class Test1 {
- public static void main(String[] args) {
-
- window1 wd = new window1();
- Thread t1=new Thread(wd);
- Thread t2=new Thread(wd);
- Thread t3=new Thread(wd);
-
- t1.setName("窗口一");
- t2.setName("窗口二");
- t3.setName("窗口三");
-
- t1.start();
- t2.start();
- t3.start();
- }
- }
- /**
- * 方式二:
- * 使用同步方法解决实现Runnable接口的线程安全问题
- * 代码的执行放在另一个方法中,声明的方式的返回值是synchronized
- *
- */
- class window2 implements Runnable{
- private int ticket = 100;
- @Override
- public void run() {
- while(true){
- show();
-
- }
-
- }
- private synchronized void show(){
- // 或者使用同步代码块:synchronized (this) {
- if (ticket > 0) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "卖票,剩余票数:" + ticket);
- ticket--;
- }
- }
- }
- public class Test2 {
- public static void main(String[] args) {
-
- window2 wd = new window2();
- Thread t1=new Thread(wd);
- Thread t2=new Thread(wd);
- Thread t3=new Thread(wd);
-
- t1.setName("窗口一");
- t2.setName("窗口二");
- t3.setName("窗口三");
-
- t1.start();
- t2.start();
- t3.start();
- }
- }
- class Bank {
- private Bank() {
- }
-
- private static Bank instance = null;
-
- public static Bank getInstance() {
-
- // 方式一:效率差
- // synchronized (Bank.class) {
- // if (instance == null) {
- // instance = new Bank();
- // }
- // return instance;
- // }
-
-
- // 方式二:效率高一点
- if (instance == null) {
- //Bank.class:是代表当前类
- synchronized (Bank.class) {
- if (instance == null) {
- instance = new Bank();
- }
- return instance;
- }
- }
- return null;
- }
- }
- class Window4 implements Runnable{
- private int ticket =100;
-
- // 1、实例化lock
- private ReentrantLock lock=new ReentrantLock(true);
- @Override
- public void run() {
- while(true){
- try {
- // 2、调用锁定方法lock();
- lock.lock();
-
- if (ticket > 0) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "销售为:" + ticket);
- ticket--;
- } else {
- break;
- }
- }finally {
- // 3、调用解锁方法:unlock()
- lock.unlock();
- }
- }
- }
- }
-
- public class Test5 {
-
- public static void main(String[] args) {
- Window4 window=new Window4();
-
- Thread t1=new Thread(window);
- Thread t2=new Thread(window);
- Thread t3=new Thread(window);
-
- t1.setName("窗口一");
- t2.setName("窗口二");
- t3.setName("窗口三");
-
- t1.start();
- t2.start();
- t3.start();
-
-
-
- }
- }
- **
- * 创建线程的方式三:实现collable接口的方式。----JDK 5.0新增
- * callable接口的方式创建多线程比Runnable接口创建多线程方式强大?
- * 1、call()可以有返回值
- * 2、call()可以抛出异常,被外面的操作捕获,获取异常的信息
- * 3、callable是支持泛型的
- * Description:
- * @author: ----千里之行,始于足下----
- * date: 2022/8/15 15:12
- */
- //1、创建一个实现callable的实现类
- class NumThread implements Callable{
- //2、实现call方法,将此线程需要执行的操作声明在call()中
- @Override
- public Object call() throws Exception {
- int sum=0;
- for (int i = 1; i <= 100; i++) {
- if(i%2==0){
- System.out.println(i);
- sum+=i;
- }
- }
- return sum;
- }
- }
- public class ThreadNew {
- public static void main(String[] args) {
- //3、创建callable接口实现类的对象
- NumThread numThread =new NumThread();
- //4、将此callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
- FutureTask futureTask =new FutureTask(numThread);
- //5、将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
- new Thread(futureTask).start();
-
- try {
- // 6、获取callable中call方法的返回值
- // get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
- Object sum = futureTask.get();
- System.out.println(sum);
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
-
-
- }
- }