zoukankan      html  css  js  c++  java
  • [Java2 入门经典]第16章 线程

    网上对线程的总结:http://lavasoft.blog.51cto.com/62575/27069

    定义表示线程的类有两种方法:

    一种是将其定义为Thread类的子类,并提供run()方法的定义来替代继承的run()方法。

    另一种方法将其定义为接口Runnable的形式。这个接口声明run()方法,然后在需要的时候在类中创建一个Thread对象。

    -------------------------------------------------------------

    16.1理解线程

    创建线程 | 停止线程 | 连接线程 | 线程调度 | 实现Runnable接口

    守护线程和用户进程 

    setDaemon(true)将线程设为守护线程。守护线程只是一个后台运行的线程,它从属于创建它的线程,所以当创建守护进程的线程结束时,守护线程也随之消亡。

    由守护线程创建的线程默认为守护线程。

    import java.io.IOException;
    
    public class TryThread extends Thread{
            public TryThread(String firstName, String secondName, long delay){
                    this.firstName = firstName;
                    this.secondName = secondName;
                    aWhile = delay;
                    setDaemon(true);//守护进程
            }
    
            public static void main(String[] args){
                    Thread first = new TryThread("Hopalong ", "Cassidy ", 200L);
                    Thread second = new TryThread("Marilyn ", "Monroe ", 300L);
                    Thread third = new TryThread("Slim ", "Pickens ", 500L);
    
                    System.out.println("Press Enter when you have had enough...n");
                    first.start();
                    second.start();
                    third.start();
    
                    try{
                            System.in.read();
                            System.out.println("Enter pressed...n");
                    } catch(IOException e){
                            System.out.println(e);
                    }
    
                    System.out.println("Ending main()");
                    return;
            }
            public void run(){
                    try{
                            while(true){
                                    System.out.print(firstName);
                                    sleep(aWhile);
                                    System.out.print(secondName + "n");
                            }
                    } catch(InterruptedException e){
                            System.out.println(firstName + secondName + e);
                    }
            }
            private String firstName;
            private String secondName;
            private long aWhile;
    
    }
    setDaemon

    将线程设置到执行状态将线程设置到中止状态

    start()                             / interrupt()

    测试线程是否仍在运行,可以调用isAlive方法。

    测试线程是否已经中断,可以调用isInterrupted方法。

    连接线程:如果一个线程中需要等待另一个线程消亡,可以调用join方法来处理希望消亡的线程。无参数调用join()将暂停当前线程,直到指定线程消亡。也可以传递一个long类型的值,指定等待的毫秒数。  代码实例http://www.cnblogs.com/jimwind/p/3259139.html

    线程调度:每个线程,在其他线程调用sleep时,都有机会执行。如果操作系统采用抢占式的任务调度,那么不在run()方法中调用sleep,程序也能运行(如果去掉sleep,也要去掉try块和catch块)。但是,如果操作系统不是以这种方式调度的,在run方法中不调用sleep,第一个线程就会独占处理器并无限地继续下去。

    即:通过调用sleep来放弃控制权,让其它线程有机会运行。

    还有一个方法,yield(),它与sleep的区别是,当调用sleep时,即使没有其他线程等待,该线程也会至少停止由实参所指定的一段时间,然而,调用yeid时,如果没有其他线程待,当前线程就马上重新开始执行。PS:那貌似yield方法好多了啊。百度了一下,跟优先级有关。

    以上,应该关注的四个方法,setDaemon, join, sleep, yield

    实现Runnable接口

    import java.io.IOException;
    
    public class JumbleNames  implements Runnable{
    
            public JumbleNames(String firstName, String secondName, long delay){
                    this.firstName  = firstName;
                    this.secondName = secondName;
                    aWhile = delay;
            }   
    
            public void run(){
                    try{
                            while(true){
                                    System.out.print(firstName);
                                    Thread.sleep(aWhile);
                                    System.out.print(secondName + "\n");
                            }   
                    } catch (InterruptedException e){ 
                            System.out.println(firstName + secondName + e); 
                    }   
            }   
            public static void main(String[] args){
                    Thread first = new Thread(new JumbleNames("Hopalong ", "Cassidy ", 200L));
                    Thread second = new Thread(new JumbleNames("Marilyn ", "Monroe ", 300L));
                    Thread third = new Thread(new JumbleNames("Slim ", "Pickens ", 500L));
    
                    first.setDaemon(true);
                    second.setDaemon(true);
                    third.setDaemon(true);
        
                    System.out.println("Press Enter when you have had enough...\n");
        
                    first.start();
                    second.start();
                    third.start();
        
                    try{
                            System.in.read();
                            System.out.println("Enter pressed...\n");
                    } catch(IOException e){ 
                            System.out.println(e);
                    }   
                    System.out.println("Ending main()");
                    return;
            }   
            private String firstName;
            private String secondName;
            private long aWhile;
    
    }
    runnable

    线程的名称: Thead first = new Thread(new JumbleNames("Hopalong ", "Cassidy ", 200L), "firstThread");

    ----------------------------------------------------------------

    16.2 管理线程

    当两个线程共享公有资源时,就要保证一个线程使用资源时,另一个线程不能修改资源。 同步处理。

    同步处理: 同步方法 | 同步语句块

    同步方法,可以使一个类对象的方法的子集(或者全部方法)互斥。

    class MyClass{
        synchronized public void method1(){
        }
        synchronized public void method2(){
        }
        public void method3(){
        }
    }
    

    如果在实际运行时,MyClass 的对象有obj1,obj2。当执行obj1.method1()时,不能执行obj1.method2()。但对于obj2执行method1还是method2没有关系。

    即,此同步处理是控制对同一对象的并发访问。不同对象使用同步实例方法是彼此独立的。

    如果对类的静态方法用同步处理,那么在任何时候该类的这些静态方法只有一个可以执行。

    将“业务”对象交给“银行”,由“银行”来处理。

    业务类:将帐户,业务类型,交易总额初始化一个业务对象。

    帐户类:将帐号,帐户余额初始化帐户。

    职员类:指明其所在的银行,为的是将业务提交给银行。实现了Runnable接口

    银行操作类:只需要一个main方法

    创建银行,创建两个此银行的职员,创建一个银行帐户;

    创建职员的线程,并启动。

    用一个for循环,创建几笔业务,职员1每次都做存款业务,职员2每次都做货歀业务。

    这里银行做业务时,必须是synchronized

    class Bank {
            synchronized public void doTransaction(Transaction transaction){
                    int balance = transaction.getAccount().getBalance();
                    switch(transaction.getTransactionType()){
                    case Transaction.CREDIT:
                            try{
                                    Thread.sleep(100);
                            } catch (InterruptedException e){ 
                                    System.out.println(e);
                            }   
                            balance += transaction.getAmount();
                    break;  
                    case Transaction.DEBIT:
                            try{
                                    Thread.sleep(150);
                            } catch (InterruptedException e){ 
                                    System.out.println(e);
                            }   
                            balance -= transaction.getAmount();
                    break;
                    default:
                            System.out.println("Invalid transaction");
                            System.exit(1);
                    }   
                    transaction.getAccount().setBalance(balance);
            }   
    }
    
    
    class Transaction {
            public static final int DEBIT = 0;
            public static final int CREDIT = 1;
            public static String[] types = {"Debit", "Credit"};
    
            public Transaction(Account account, int transactionType, int amount){
                    this.account = account;
                    this.transactionType = transactionType;
                    this.amount = amount;    
            }   
            public Account getAccount(){
                    return account;
            }   
            public int getTransactionType(){
                    return transactionType;
            }   
            public int getAmount(){
                    return amount;
            }   
            public String toString(){
                    return types[transactionType] + " A/C: " + " :$" + amount;
            }   
            private Account account;
            private int amount;
            private int transactionType;
    
    }
    
    public class Account {
            public Account(int accountNumber, int balance){
                    this.accountNumber = accountNumber;
                    this.balance = balance;
            }   
            public int getBalance(){
                    return balance;
            }   
            public void setBalance(int balance) {
                    this.balance = balance;
            }   
        
            public int getAccountNumber() {
                    return accountNumber;
            }   
        
            public String toString() {
                    return "A//C No. " + accountNumber+" :$"+balance;
            }   
            private int balance;
            private int accountNumber;
    }
    
    public class Clerk implements Runnable {
            public Clerk(Bank theBank){
                    this.theBank = theBank;
                    inTray = null;
            }   
            public void doTransaction(Transaction transaction){
                    inTray = transaction;
            }   
            public void run(){
                    while(true){
                            while(inTray == null){
                                    try{
                                            Thread.sleep(150);
                                    } catch (InterruptedException e){ 
                                            System.out.println(e);
                                    }   
                            }   
                            theBank.doTransaction(inTray);
                            inTray = null;
                    }   
            }   
            public boolean isBusy(){
                    return inTray != null;
            }   
            private Bank theBank;
            private Transaction inTray;
        
    }
    
    import java.util.Random;
    
    public class BankOperation {
            public static void main(String[] args){
                    int initialBalance = 500;
                    int totalCredits = 0;
                    int totalDebits = 0;
                    int transactionCount = 20;
    
    
                    //Create the account, the bank, and the clerks...
                    Bank theBank = new Bank();
                    Clerk clerk1 = new Clerk(theBank);
                    Clerk clerk2 = new Clerk(theBank);
                    Account account = new Account(1, initialBalance);
    
                    //Create the threads for the clerks as daemon, and start them off
                    Thread clerk1Thread = new Thread(clerk1);
                    Thread clerk2Thread = new Thread(clerk2);
                    clerk1Thread.setDaemon(true);
                    clerk2Thread.setDaemon(true);
                    clerk1Thread.start();
                    clerk2Thread.start();
    
                    //Generate the transactions of each type and pass to the clerks
                    Random rand = new Random();
                    Transaction transaction;
                    int amount = 0;
                    for(int i = 0; i<=transactionCount; i++){
                            amount = 50 + rand.nextInt(26);
                            transaction = new Transaction(account,
                                                            Transaction.CREDIT,
                                                            amount);
                            totalCredits += amount;
    
                            while(clerk1.isBusy()){
                                    try{
                                            Thread.sleep(25);
                                    } catch(InterruptedException e){ 
                                            System.out.println(e);
                                    }   
                            }   
                            clerk1.doTransaction(transaction);
                            amount = 30 + rand.nextInt(31);
                            transaction = new Transaction(account,
                                                            Transaction.DEBIT,
                                                            amount);
                            totalDebits += amount;
                            while(clerk2.isBusy()){
                                    try{
                                            Thread.sleep(25);
                                    } catch(InterruptedException e){
                                            System.out.println(e);
                                    }
                            }
                            clerk2.doTransaction(transaction);
                    }
    
    
                    //Wait until both clerks are done
                    while(clerk1.isBusy() || clerk2.isBusy()){
                            try{
                                    Thread.sleep(25);
                            } catch(InterruptedException e){
                                    System.out.println(e);
                            }
                    }
    
                    //Now output the results
                    System.out.println(
                                    "Original balance:      $"+initialBalance +"n"+
                                    "Total credits:         $"+totalCredits+"n"+
                                    "Total debits:          $"+totalDebits+"n"+
                                    "Final balance:         $"+account.getBalance()+"n"+
                                    "Should be:             $"+(initialBalance+totalCredits - totalDebits));
    
            }
    }
    =======================================
    class Bank {
    //      synchronized 
            public void doTransaction(Transaction transaction){
    //              int balance = transaction.getAccount().getBalance();            
                    switch(transaction.getTransactionType()){
                    case Transaction.CREDIT:
                    synchronized(transaction.getAccount()){
                            System.out.println("Start credit of "+ transaction.getAccount() +" amount: "+ transaction.getAmount());
                            int balance = transaction.getAccount().getBalance();
                            try{
                                    Thread.sleep(100);
                            } catch (InterruptedException e){ 
                                    System.out.println(e);
                            }   
                            balance += transaction.getAmount();
                            transaction.getAccount().setBalance(balance);
                            System.out.println(" End credit of "+ transaction.getAccount()+" amount: "+ transaction.getAmount());
                    }    
                    break;  
                    case Transaction.DEBIT:
                    synchronized(transaction.getAccount()){
                            System.out.println("Start debit of "+ transaction.getAccount()+" amount: "+ transaction.getAmount());
                            int balance = transaction.getAccount().getBalance();
                            try{
                                    Thread.sleep(150);
                            } catch (InterruptedException e){ 
                                    System.out.println(e);
                            }   
                            balance -= transaction.getAmount();
                            transaction.getAccount().setBalance(balance);
                            System.out.println(" End debit of "+ transaction.getAccount()+" amount "+ transaction.getAmount());
                    }   
                    break;
                    default:
                            System.out.println("Invalid transaction");
                            System.exit(1);
                    }   
            }   
    }
    
    import java.util.Random;
    
    public class BankOperationMultiAccount {
            public static void main(String[] args){
                    int[] initialBalance = {500,800};
                    int[] totalCredits = new int[initialBalance.length];
                    int[] totalDebits = new int[initialBalance.length];
                    int transactionCount = 20; 
    
    
                    //Create the account, the bank, and the clerks...
                    Bank theBank = new Bank();
                    Clerk clerk1 = new Clerk(theBank);
                    Clerk clerk2 = new Clerk(theBank);
    //              Account account = new Account(1, initialBalance);
                    Account[] accounts = new Account[initialBalance.length];
                    for(int i =0; i<initialBalance.length; i++){
                            accounts[i] = new Account(i+1, initialBalance[i]);
                            totalCredits[i] = totalDebits[i] = 0;
                    }   
    
                    //Create the threads for the clerks as daemon, and start them off
                    Thread clerk1Thread = new Thread(clerk1);
                    Thread clerk2Thread = new Thread(clerk2);
                    clerk1Thread.setDaemon(true);
                    clerk2Thread.setDaemon(true);
                    clerk1Thread.start();
                    clerk2Thread.start();
    
                    //Generate the transactions of each type and pass to the clerks
                    Random rand = new Random();
                    Transaction transaction;
                    int amount = 0;
                    int select = 0;
                    for(int i = 0; i<=transactionCount; i++){
                            select = rand.nextInt(accounts.length);
                            amount = 50 + rand.nextInt(26);
                            transaction = new Transaction(accounts[select],
                                                            Transaction.CREDIT,
                                                            amount);
                            totalCredits[select] += amount;
    
                            while(clerk1.isBusy()){
                                    try{
                                            Thread.sleep(25);
                                    } catch(InterruptedException e){
                                            System.out.println(e);
                                    }
                            }
                            clerk1.doTransaction(transaction);
    
                            select = rand.nextInt(accounts.length);
                            amount = 30 + rand.nextInt(31);
                            transaction = new Transaction(accounts[select],
                                                            Transaction.DEBIT,
                                                            amount);
                            totalDebits[select] += amount;
                            while(clerk2.isBusy()){
                                    try{
                                            Thread.sleep(25);
                                    } catch(InterruptedException e){
                                            System.out.println(e);
                                    }
                            }
                            clerk2.doTransaction(transaction);
                    }
    
    
                    //Wait until both clerks are done
                    while(clerk1.isBusy() || clerk2.isBusy()){
                            try{
                                    Thread.sleep(25);
                            } catch(InterruptedException e){
                                    System.out.println(e);
                            }
                    }
    
                    //Now output the results
                    for(int i=0; i<accounts.length; i++){
                            System.out.println(
                                            "Account Number:"+accounts[i].getAccountNumber() + "n"+
                                            "Original balance:      $"+initialBalance[i] +"n"+
                                            "Total credits:         $"+totalCredits[i]+"n"+
                                            "Total debits:          $"+totalDebits[i]+"n"+
                                            "Final balance:         $"+accounts[i].getBalance()+"n"+
                                            "Should be:             $"+(initialBalance[i]+totalCredits[i] - totalDebits[i])+"n");
                    }
            }
    }
    
    
    =====================================================================
    =====================================================================
    public class Clerk implements Runnable {
            public Clerk(Bank theBank){
                    this.theBank = theBank;
                    inTray = null;
            }   
            synchronized public void doTransaction(Transaction transaction){
    //              inTray = transaction;
                    while(inTray != null){
                            try{
                                    wait();
                            } catch (InterruptedException e){ 
                                    System.out.println(e);
                            }   
                    }   
                    inTray = transaction;
                    notifyAll();
            }   
            synchronized public void run(){
                    while(true){
                            while(inTray == null){
                                    try{
    //                                      Thread.sleep(150);
                                            wait();
                                    } catch (InterruptedException e){ 
                                            System.out.println(e);
                                    }   
                            }   
                            theBank.doTransaction(inTray);
                            inTray = null;
                            notifyAll();    
                    }   
            }   
            synchronized public void isBusy(){
                    while(inTray != null){
                            try{
                                    wait();
                            } catch(InterruptedException e){ 
                                    System.out.println(e);
                            }   
                    }   
                    return;
    //              return inTray != null;
            }   
            private Bank theBank;
            private Transaction inTray;
    }
    
    import java.util.Random;
    
    public class BankOperationMultiAccount {
            public static void main(String[] args){
                    int[] initialBalance = {500,800};
                    int[] totalCredits = new int[initialBalance.length];
                    int[] totalDebits = new int[initialBalance.length];
                    int transactionCount = 20; 
    
    
                    //Create the account, the bank, and the clerks...
                    Bank theBank = new Bank();
                    Clerk clerk1 = new Clerk(theBank);
                    Clerk clerk2 = new Clerk(theBank);
    //              Account account = new Account(1, initialBalance);
                    Account[] accounts = new Account[initialBalance.length];
                    for(int i =0; i<initialBalance.length; i++){
                            accounts[i] = new Account(i+1, initialBalance[i]);
                            totalCredits[i] = totalDebits[i] = 0;
                    }   
    
                    //Create the threads for the clerks as daemon, and start them off
                    Thread clerk1Thread = new Thread(clerk1);
                    Thread clerk2Thread = new Thread(clerk2);
                    clerk1Thread.setDaemon(true);
                    clerk2Thread.setDaemon(true);
                    clerk1Thread.start();
                    clerk2Thread.start();
    
                    //Generate the transactions of each type and pass to the clerks
                    Random rand = new Random();
                    Transaction transaction;
                    int amount = 0;
                    int select = 0;
                    for(int i = 0; i<=transactionCount; i++){
                            select = rand.nextInt(accounts.length);
                            amount = 50 + rand.nextInt(26);
                            transaction = new Transaction(accounts[select],
                                                            Transaction.CREDIT,
                                                            amount);
                            totalCredits[select] += amount;
    
                            clerk1.doTransaction(transaction);
    
                            select = rand.nextInt(accounts.length);
                            amount = 30 + rand.nextInt(31);
                            transaction = new Transaction(accounts[select],
                                                            Transaction.DEBIT,
                                                            amount);
                            totalDebits[select] += amount;
    
                            clerk2.doTransaction(transaction);
                    }
    
    
                    //Wait until both clerks are done
    
                    clerk1.isBusy();
                    clerk2.isBusy();
    
                    //Now output the results
                    for(int i=0; i<accounts.length; i++){
                            System.out.println(
                                            "Account Number:"+accounts[i].getAccountNumber() + "n"+
                                            "Original balance:      $"+initialBalance[i] +"n"+
                                            "Total credits:         $"+totalCredits[i]+"n"+
                                            "Total debits:          $"+totalDebits[i]+"n"+
                                            "Final balance:         $"+accounts[i].getBalance()+"n"+
                                            "Should be:             $"+(initialBalance[i]+totalCredits[i] - totalDebits[i])+"n");
                    }
            }
    }
    thread

    同步语句块

    见上面thread代码中“==============”以下的代码,因为只改了Bank,新增了BankOperationMultiAccount

    死锁

    thread1
    run(){
        synchronized(theObject){
            sleep(1000);
            theOtherObject.method2();
        }
    }
    
    thread2
    run(){
        synchronized(theOtherObject){
            sleep(1000);
            theObject.method1();
        }
    }
    

    线程间通信

    wait() | notify() | notifyAll()

    Object类定义了以一3个方法,但只能在同步方法或同步代码块中调用这些方法。

    synchronized(anObject){
        while(condition-not-met)
            anObject.wait();
    }
    

    当调用wait时,线程会将操作挂起,直到同步于同一对象的另外某个线程调用了notify方法。

    代码在thread代码

    =============================

    =============================

    后面

    在Clerk中同步方法doTransaction,但是这个方法运行在主线程中,若其wait,其实将主线程挂起,只有在run中的wait才是将clerk1对象挂起。

  • 相关阅读:
    OpenAL
    VS2013关于“当前不会命中断点源代码与原始版本不同”的BUG
    Windows中的句柄
    (转)OpenGL中位图的操作(glReadPixels,glDrawPixels和glCopyPixels应用举例)
    全局变量的初始化顺序
    与时间有关的windows函数
    unity中的协程
    Unity3d碰撞检测中碰撞器与触发器的区别
    unity脚本入门
    面试总结关于Spring面试问题(精选)
  • 原文地址:https://www.cnblogs.com/jimwind/p/2755834.html
Copyright © 2011-2022 走看看