java线程

    科技2022-07-17  121

    线程

    线程创建

    继承Thread,重写run方法实现Runnable接口,实现run方法实现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();//释放所有等待的线程 } } } }

    线程安全

    触发条件

    多线程并发有共享数据共享数据有修改操作 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); }
    Processed: 0.011, SQL: 8