[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对象挂起。

你可能感兴趣的:(java)