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

  • 相关阅读:
    素数路径Prime Path POJ3126 素数,BFS
    Fliptile POJ3279 DFS
    Find the Multiple POJ1426
    洗牌Shuffle'm Up POJ3087 模拟
    棋盘问题 POJ1321 DFS
    抓住那只牛!Catch That Cow POJ3278 BFS
    Dungeon Master POJ2251 三维BFS
    Splitting into digits CodeForce#1104A
    Ubuntu下手动安装Nvidia显卡驱动
    最大连续子序列和
  • 原文地址:https://www.cnblogs.com/jimwind/p/2755834.html
Copyright © 2011-2022 走看看