• Java多线程详解(二)


         

    评论区留下邮箱可获得《Java多线程设计模式详解》

    转载请指明来源

     1)后台线程

      后台线程是为其他线程服务的一种线程,像JVM的垃圾回收线程就是一种后台线程。后台线程总是等到非后台线程死亡之后,后台线程没有了服务对象,不久就会自动死亡,不再复活。利用setDaemon方法可以把一个线程设置为后台线程,但必须在线程启动之前调用。

       例如 :

    /*
     * @author  wxismeit@163.com
     */
    public class DaemonThread extends Thread {
    	public void run() {
    		for(int i=0; i<100; i++) {
    			System.out.println(getName() + " " + i);
    		}
    	}
    
    	public static void main(String[] args) throws InterruptedException {
    		DaemonThread dt = new DaemonThread();
    		dt.setDaemon(true);//必须在启动线程之前调用
    		dt.start();
    		System.out.println(dt.isDaemon());//true
    		for(int i=0; i<10; i++) {
    			System.out.println(Thread.currentThread().getName() + " " + i);
    			Thread.sleep(1000);//让当前线程睡眠1s,进入阻塞状态。其他线程可以执行
    		}
    		//在主线程main结束不久,后台线程st也会死亡
    
    	}
    
    }
    


     

    2)线程让步 :yield

    让当前线程暂停,但不阻塞该线程。让该线程转入就绪状态。系统根据优先级重新调度线程。可以使用setPriority方法设置线程的优先级。

    例如:

    public class YieldThread extends Thread {
    	public YieldThread(String name) {
    		super(name);
    	}
    	public void run() {
    		for(int i=0; i<50; i++) {
    			System.out.println(getName() + " " + i);
    			if(i == 20) {
    				Thread.yield();//让当前线程让步
    			}
    		}
    	}
    
    	public static void main(String[] args) {
    		YieldThread yt1 = new YieldThread("high");
    		YieldThread yt2 = new YieldThread("low");
    		yt1.setPriority(MAX_PRIORITY);//优先级设为高级
    		yt1.start();
    		yt2.setPriority(MIN_PRIORITY);//优先级设为低级
    		yt2.start();
    	}
    
    }
    

    3)sleep  和 yield的区别

    sleep暂停时,进入阻塞状态,其他线程会执行,不考虑优先级。而yield暂停时进入就绪状态。只会给优先级相同或更高的线程执行机会。

    4)线程同步

    在银行取钱时 如果两个线程同时操作一个账户,就会出现不应该的错误,这就是线程不安全的。那么如何能让线程成为安全的呢。

    public class Account {
    	private String accountNo;
    	private double balance;
    	public Account() {};
    	public Account(String a,double b) {
    		accountNo = a;
    		balance = b;
    	}
    	public void setaccountNo(String accountNo) {
    	      this.accountNo = accountNo;
    	}
    	public void setbalance(double balance) {
    		this.balance = balance;
    	}
    	public String getaccountNo() {
    		return this.accountNo;
    	}
    	public double getbalance() {
    		return this.balance;
    	}
    	//重写hashcode方法
    	public int hashCode() {
    		return accountNo.hashCode();
    	}
    	//重写equals方法
    	public boolean equals(Object obj) {
    		if(this == obj) return true;
    		if(obj != null && obj.getClass() == Account.class) {
    			Account a = (Account)obj;
    			return a.getaccountNo().equals(accountNo);
    		}
    		return false;
    	}
    	
    
    }
    


     

    public class Withdraw extends Thread{
    	private Account account;
    	private double drawNo;
    	public Withdraw(String name, Account a, double d) {
    		super(name);
    		account = a;
    		drawNo = d;
    	}
    	
    	public void run() {
    		//synchronized(account) {//锁定对象,其他线程无法获得,无法修改账户。
    		if(account.getbalance() >= drawNo) {
    			System.out.println("所取钱数为 :" + drawNo);
    			try {
    				Thread.sleep(1000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			account.setbalance(account.getbalance() - drawNo);
    			System.out.println("余额为: " + account.getbalance());
    		}else {
    			System.out.println("取钱失败!");
    		//}	
    		}
    	}
    	
    
    
    }
    


     

    public class DrawMoney {
    
    	public static void main(String[] args) {
    		Account ac = new Account("wangxu", 1000);
    		new Withdraw("甲", ac, 800).start();
    		new Withdraw("乙", ac, 800).start();
    	}
    }
    


    如上代码所示,在修改能够引发线程不安全问题的时候,就要锁定。这时可以用代码同步块和同步方法来锁定,所用关键字为synchronized。具体不再赘述。

    4)同步锁

    为了更灵活的解决线程安全问题,Java引入了同步锁。有读写锁,可重入锁等。

    举个简单的例子:

    import java.util.concurrent.locks.ReentrantLock;
    
    
    public class lock {
    	private final ReentrantLock lock = new ReentrantLock();
    	//需要线程安全的方法
    	public void f() {
    		lock.lock();//加锁
    		try{
    			//...
    		}finally {
    			lock.unlock();//释放锁
    		}
    	}
    
    }
    


    关于死锁和线程通信下次更新。

    评论区留下邮箱可获得《Java多线程设计模式详解》

    转载请指明来源

  • 相关阅读:
    Java Stream 去重对象
    CentOS7安装JDK8
    CentOS7安装Tomcat9
    MySQL 8.0 安装
    面相对象7大原则
    Spring Boot MyBatis连接MySQL数据库
    win11右键改回win10风格,win10右键改回win11风格,不用重启
    【转载】NetCore 开发实战(目录整理)
    viewState cookie session _VIEWSTATE
    外部JS得到客户端ID
  • 原文地址:https://www.cnblogs.com/wxisme/p/4363755.html
Copyright © 2020-2023  润新知