java多线程

来源:互联网 发布:软件学报审稿流程 编辑:程序博客网 时间:2024/04/20 10:58

意义

  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();    }}
0 0
原创粉丝点击