java线程

线程

线程状态图

线程创建

  1. 继承Thread,重写run方法
  2. 实现Runnable接口,实现run方法
  3. 实现Callable接口,实现call方法(带返回值)
        //创建服务
        ExecutorService service= Executors.newFixedThreadPool(1);
        //提交执行
        Future submit = service.submit(callDemo1);
        //获取结果
        System.out.println(submit.get());
        //关闭线程
        service.shutdown();

常用方法

  • start()(开启线程)
  • sleep(1000)(休眠1秒,不释放锁)
  • setName()(设置线程的名字)
  • getName()(获取线程的名字)
  • getPriority()(获得当前的优先权,最高10,最低1,默认5。)
  • interrupt()(终止休眠)
        Thread thread = new Thread(new SleepDemo1());
        thread.setName("小花");//设置线程名字
        thread.start();//开启线程
        System.out.println(thread.getName());//获取线程名
        System.out.println(thread.getPriority());//获取优先级,默认为5
        try {
            Thread.sleep(1000*5);//5秒后
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.interrupt();//终止休眠,实际上就是在thread这个线程休眠的时候出异常,这样就会直接执行catch的语句,终止休眠。

    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开启了");
        try {
            Thread.sleep(1000*60*24);//睡一天
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"结束了");
    }
//小花
//5
//小花开启了
//java.lang.InterruptedException: sleep interrupted
//	at java.lang.Thread.sleep(Native Method)
//	at base.线程.SleepDemo1.run(SleepDemo1.java:31)
//	at java.lang.Thread.run(Thread.java:748)
//小花结束了
  • yield()(礼让线程)
@Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if(i%5==0){
                Thread.yield();//礼让线程,让当前线程回到就绪状态,重新开始抢夺时间片。可能抢到也可能抢不到。
            }
            System.out.println(Thread.currentThread().getName()+"-->已下载"+i+"%。");
        }
    }

    public static void main(String[] args) {
        new Thread(new RunnableDemo1(),"图片").start();
        for (int i = 1; i <= 100; i++) {
            System.out.println(Thread.currentThread().getName()+"正在执行"+i+"。");
        }
    }
//main正在执行15。
//图片-->已下载1%。
//图片-->已下载2%。
//图片-->已下载3%。
//图片-->已下载4%。结束后i=5,执行yield()
此时图片线程又抢到了时间片,继续执行run()
//图片-->已下载5%。
//图片-->已下载6%。
//图片-->已下载7%。
//图片-->已下载8%。
//图片-->已下载9%。
//图片-->已下载10%。
//图片-->已下载11%。
此时main线程抢到了时间片,继续执行run()
//main正在执行16。
//main正在执行17。
//main正在执行18。
//main正在执行19。
  • join()(合并线程)
        try {
            t1.join();//合并线程。将t1线程合并到当前线程main,让当前线程阻塞,直到t1线程执行完。
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
  • setDeamon()(设置成守护线程)

线程分为用户线程和守护线程。只有当所有用户线程都结束,守护线程才会结束。

  • wait()(wait其实是Object的方法,线程等待并释放锁)
  • notify()(恢复当前等待的线程,不释放锁)
  • notifyAll()(恢复所有等待的线程)
public class ProducerDemo2 {
    public static void main(String[] args) {
        List list = new ArrayList();
        new Thread(new Producer1(list), "A").start();
        new Thread(new Customer1(list), "B").start();
    }
}
class Producer1 implements Runnable {
    private List list;

    public Producer1(List list) {
        this.list = list;
    }
    @Override
    public void run() {
        while (true) {
            synchronized (list) {
                //仓库满了
                if (list.size() > 0) {
                    try {
                        list.wait();//当前线程等待,执行另外的线程
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //仓库空了
                Object obj = new Object();
                list.add(obj);//生产一个
                System.out.println(Thread.currentThread().getName() + "生产了-->" + obj);
                list.notifyAll();//释放所有等待的线程
            }
        }
    }
}
class Customer1 implements Runnable {
    private List list;

    public Customer1(List list) {
        this.list = list;
    }
    @Override
    public void run() {
        while (true) {
            synchronized (list) {
                //仓库空了
                if (list.size() == 0) {
                    try {
                        list.wait();//线程等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //仓库满了就要消费了
                Object obj = list.remove(0);//消费一个
         System.out.println(Thread.currentThread().getName() + "消费了-->" + obj);
                list.notifyAll();//释放所有等待的线程

            }
        }
    }
}

线程安全

触发条件

  1. 多线程并发
  2. 有共享数据
  3. 共享数据有修改操作
public class BackDemo1 {
    public static void main(String[] args) {
        Account act=new Account(10000);
        //两个线程对同一个对象操作
        new Thread(new Bank(act),"A").start();
        new Thread(new Bank(act),"B").start();
        //A还剩5000.0
        //B还剩5000.0
    }
}
class Account {
    //账户余额
    private double balance;
    public Account(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
    //取钱
    void getMoney(double money){

            double before = this.getBalance();
            double after = before - money;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        //出现线程安全问题
            this.setBalance(after);

    }
}
class Bank implements Runnable{
    private Account act;

    public Bank(Account act) {
        this.act = act;
    }

    @Override
    public void run() {
        double money=5000;
        act.getMoney(money);
        System.out.println(Thread.currentThread().getName()+"还剩"+act.getBalance());
    }
}

解决方法

synchronized(线程同步)

synchronized (共享对象){
    //代码
}
1.在代码块中加上synchronized
        //在代码块中加上synchronized
        synchronized (this) {
            double before = this.getBalance();
            double after = before - money;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.setBalance(after);
        }
2.在方法上加synchronized

共享对象只能是this,同步范围是一整个方法。对象锁,一百个对象一百个锁。

**优点:**方便、简洁。

**缺点:**范围大,性能低。

    
    synchronized void getMoney(double money){
            double before = this.getBalance();
            double after = before - money;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.setBalance(after);

    }
3.在静态方法上加synchronized

类锁,一百个对象一个锁。

 synchronized static void getMoney(double money){
            double before = this.getBalance();
            double after = before - money;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.setBalance(after);

    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值