java线程池实例

通过工作队列类(WorkQueue)实现的java线程池。WorkQueue类实现线程池的初始化,线程的分配的功能。

本文使用的代码来源于:

1-Java theory and practice: Thread pools and work queues by Brian Goetz

2-《Core Java 8th edition》 Chapter 14. Multithreading 中银行账户间转账的例子

几点说明:

1-wait(),notify(),notifyAll()不属于Thread类,而属于Object类。也就是说所有对象都能使用这些方法。每个对象都有锁。

WorkQueue类:

package ThreadPool;

import java.util.LinkedList;

public class WorkQueue {

    private final int nThreads;

    private final PoolWorker[] threads;

    private final LinkedList queue;

    public WorkQueue(int nThreads) {
        this.nThreads = nThreads;
        queue = new LinkedList();
        threads = new PoolWorker[nThreads];

        for (int i = 0; i < nThreads; i++) {
            threads[i] = new PoolWorker();
            threads[i].start();
        }
    }

    public void execute(Runnable r) {
        synchronized (queue) {
            queue.addLast(r);
            queue.notify();
        }
    }

    private class PoolWorker extends Thread {

        @Override
        public void run() {
            Runnable r;

            while (true) {
                synchronized (queue) {
                    while (queue.isEmpty()) {
                        try {
                            queue.wait();//放弃锁
                        } catch (InterruptedException ignored) {
                        }
                    }

                    System.out.println("------Thread " + queue.getFirst());
                    r = (Runnable) queue.removeFirst();
                }

                // If we don't catch RuntimeException,
                // the pool could leak threads
                try {
                    r.run();
                } catch (RuntimeException e) {
                    // You might want to log something here
                }
            }
        }
    }

}
Bank类:

package ThreadPool;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * A bank with a number of bank accounts that uses locks for serializing access.
 * 
 * @version 1.30 2004-08-01
 * @author Cay Horstmann
 */
public class Bank {

    /**
     * Constructs the bank.
     * 
     * @param n the number of accounts
     * @param initialBalance the initial balance for each account
     */
    public Bank(int n, double initialBalance) {
        accounts = new double[n];
        for (int i = 0; i < accounts.length; i++) {
            accounts[i] = initialBalance;
        }
        bankLock = new ReentrantLock();
        sufficientFunds = bankLock.newCondition();
    }

    /**
     * Transfers money from one account to another.
     * 
     * @param from the account to transfer from
     * @param to the account to transfer to
     * @param amount the amount to transfer
     */
    public void transfer(int from, int to, double amount) throws InterruptedException {
        bankLock.lock();
        try {
            while (accounts[from] < amount) {
                sufficientFunds.await();
            }
            System.out.print(Thread.currentThread());
            accounts[from] -= amount;
            System.out.printf(" %10.2f from %d to %d", amount, from, to);
            accounts[to] += amount;
            System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
            sufficientFunds.signalAll();
        } finally {
            bankLock.unlock();
        }
    }

    /**
     * Gets the sum of all account balances.
     * 
     * @return the total balance
     */
    public double getTotalBalance() {
        bankLock.lock();
        try {
            double sum = 0;

            for (double a : accounts) {
                sum += a;
            }

            return sum;
        } finally {
            bankLock.unlock();
        }
    }

    /**
     * Gets the number of accounts in the bank.
     * 
     * @return the number of accounts
     */
    public int size() {
        return accounts.length;
    }

    private final double[] accounts;

    private Lock bankLock;

    private Condition sufficientFunds;
}
TransferRunnable类:

package ThreadPool;

/**
 * A runnable that transfers money from an account to other accounts in a bank.
 * 
 * @version 1.30 2004-08-01
 * @author Cay Horstmann
 */
public class TransferRunnable implements Runnable {

    /**
     * Constructs a transfer runnable.
     * 
     * @param b the bank between whose account money is transferred
     * @param from the account to transfer money from
     * @param max the maximum amount of money in each transfer
     */
    public TransferRunnable(Bank b, int from, double max) {
        bank = b;
        fromAccount = from;
        maxAmount = max;
    }

    @Override
    public void run() {
        try {
            // while (true) {
            int toAccount = (int) (bank.size() * Math.random());
            double amount = maxAmount * Math.random();
            bank.transfer(fromAccount, toAccount, amount);
            // Thread.sleep((int) (DELAY * Math.random()));
            // }
        } catch (InterruptedException e) {
        }
    }

    private Bank bank;

    private int fromAccount;

    private double maxAmount;

    private int DELAY = 10;
}
PoolTest类:

package ThreadPool;

import synchBank.Bank;
import synchBank.TransferRunnable;

public class PoolTest {

    public static void main(String[] args) {
        WorkQueue wQueue = new WorkQueue(5);
        Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE);
        int i;
        for (i = 0; i < NACCOUNTS; i++) {
            TransferRunnable r = new TransferRunnable(b, i, INITIAL_BALANCE);
            wQueue.execute(r);
        }

    }

    public static final int NACCOUNTS = 100;

    public static final double INITIAL_BALANCE = 1000;

}

使用线程池后,线程数量保持在5个。WorkQueue类完成线程的分配和回收。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值