java多线程

意义

  1. 提高CPU的使用率
  2. 提高应用程序的使用率

实现方案

  1. 继承Thread类
  2. 实现Runnable接口

调度和优先级

调度:分时调度,抢占式调度 (Java采用的是该调度方式)
优先级:范围是1-10,默认是5

生命周期

  1. 新建 – 就绪 – 运行 – 阻塞 – 就绪 – 运行 – 死亡
  2. 新建 – 就绪 – 运行 – 死亡

死锁问题

两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象。

 public class DieLockDemo {
    public static void main(String[] args) {
        DieLock dl1 = new DieLock(true);
        DieLock dl2 = new DieLock(false);

        dl1.start();
        dl2.start();
    }
}

public class MyLock {
    // 创建两把锁对象
    public static final Object objA = new Object();
    public static final Object objB = new Object();
}

public class DieLock extends Thread {
    private boolean flag;
    public DieLock(boolean flag) {
        this.flag = flag;
    }
    @Override
    public void run() {
        if (flag) {
            synchronized (MyLock.objA) {
                System.out.println("if objA");
                synchronized (MyLock.objB) {
                    System.out.println("if objB");
                }
            }
        } else {
            synchronized (MyLock.objB) {
                System.out.println("else objB");
                synchronized (MyLock.objA) {
                    System.out.println("else objA");
                }
            }
        }
    }
}

以售票为例子记录多线程下存在的问题

public class SellTicket implements Runnable {
    // 定义100张票
    private int tickets = 100;

    @Override
    public void run() {
        while (true) {
            // t1,t2,t3三个线程
            if (tickets > 0) {
                // 模拟
                try {
                    Thread.sleep(100); //t1进来了并休息,t2进来了并休息,t3进来了并休息,
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");
                //可能会出现的问题:
                //窗口1正在出售第100张票
                //窗口2正在出售第100张票
                //...
                //窗口1正在出售第1张票,tickets=0
                //窗口2正在出售第0张票,tickets=-1
                //窗口3正在出售第-1张票,tickets=-2
            }
        }
    }
}

上面的问题是因为线程能同时进入代码块,解决的方法是对操作共享数据的地方加锁

public class SellTicket implements Runnable {
    // 定义100张票
    private static int tickets = 100;
    // 定义同一把锁
    private Object obj = new Object();

    //方式1:锁是唯一的任意的
    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()
                            + "正在出售第" + (tickets--) + "张票 ");
                }
            }
        }
    }

    @Override
    public void run() {
        while (true) {
            sellTicket();
        }
    }

    //方式2:
    private void sellTicket() {
        synchronized (d) {
            if (tickets > 0) {
            try {
                    Thread.sleep(100);
            } catch (InterruptedException e) {
                    e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()
                        + "正在出售第" + (tickets--) + "张票 ");
            }
        }
    }

    //方式3:同步加在方法上此时的锁是this
     private synchronized void sellTicket() {
            if (tickets > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 ");
        }
    }

    //方式4:同步加在方法上此时的锁是类字节码文件对象
    private static synchronized void sellTicket() {
        if (tickets > 0) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 ");
        }
   }
}

生产者消费者

public class Student {
    private String name;
    private int age;
    private boolean flag; // 默认情况是没有数据,如果是true,说明有数据

    public synchronized void set(String name, int age) {
        // 如果有数据,就等待
        if (this.flag) {
            try {
                this.wait();3. //可以不指定时间,也可以指定时间,释放锁;等待直到get()取走
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 1. 设置数据
        this.name = name;
        this.age = age;

        // 修改标记
        this.flag = true;
        this.notify();//提醒get()要拿数据了
    }

    public synchronized void get() {
        // 如果没有数据,就等待
        if (!this.flag) {
            try {
                this.wait();//4. 等待直到set()设置数据
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 2. 获取数据
        System.out.println(this.name + "---" + this.age);

        // 修改标记
        this.flag = false;
        this.notify();//提醒set()要设置数据了
    }
}
public class SetThread implements Runnable {
    private Student s;
    private int x = 0;

    public SetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            if (x % 2 == 0) {
                s.set("java", 30);
            } else {
                s.set("scala", 10);
            }
            x++;
        }
    }
}

public class GetThread implements Runnable {
    private Student s;

    public GetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            s.get();
        }
    }
}

public class StudentDemo {
    public static void main(String[] args) {
        //创建资源
        Student s = new Student();

        //设置和获取的类
        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s);

        //线程类
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt);

        //启动线程
        t1.start();
        t2.start();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值