JAVA实现网络编程之并发编程

一.并发与并行

    个人理解并发就是在时间上运行程序(即不同任务在不同时间片上运行),并行就是在空间上运行程序(即不同任务在不同处理器或计算机上运行)。

 

二.Java中的Thread类

    1.Thread类通过实现Runnable接口

    2.线程池(ThreadPool)用来管理线程的数量

    我们先用一个例子实现:

       1.创建并启动100个线程,每个线程都往同一个账户添加一元。

       2.定义一个名为Account类模拟账户,一个名为AddAYuanTask的类用来向账户里添加一元。

       程序如下

第一版Account
 1 import java.util.concurrent.*;
 2 
 3 public class AccountWithoutSync {
 4     private static Account account = new Account();
 5     
 6     public static void main(String[] args)
 7     {
 8         ExecutorService executor = Executors.newCachedThreadPool();
 9         
10         for(int i = 0; i < 100; i++)
11         {
12             executor.execute(new AddOneYuanTask());
13         }
14         
15         executor.shutdown();
16         
17         while(!executor.isTerminated())
18         {
19             
20         }
21         
22         System.out.println("What is balance? " + account.getBalance());
23     }
24     
25     //Inner class
26     private static class AddOneYuanTask implements Runnable
27     {
28         public void run()
29         {
30             account.deposit(1);
31         }
32     }
33     
34     private static class Account
35     {
36         private int balance = 0;
37         
38         public int getBalance()
39         {
40             return balance;
41         }
42         
43         public void deposit(int amount)
44         {
45             int newBalance = balance + amount;
46             
47                         //人为地制造延时  
48             try
49             {
50                 Thread.sleep(5);
51             }
52             catch(InterruptedException ex)
53             {
54             }
55             
56             balance = newBalance;
57         }
58     }
59 }

   我们运行一下发现balance为4或5,这是个错误的结果,如果一个类的对象在多线程程序中导致竞争状态,则称这个类为线程不安全的。所以这个任务是线程不安全的。

三.用同步完善程序

   用互斥锁来实现同步,即在一任务开始执行时加锁,执行完毕后释放锁。在释放锁之前其它任务无法执行。同步完全可以避免竞争状态的产生,但有的时候还需要线程之间的相互合作。

   然后增加一个向账户提款(Withdraw)的任务,当余额小于取款数时,等待新存入的存款。

   Account类添加

   private static Lock lock = new ReentrantLock();  //创建一个锁

   private static Condition newDeposit = lock.newCondition();  //实现一个条件

    Account类中应用互斥锁的的方法如下

withdraw和deposit

   然后程序相应的修改修改

第二版Account
 1     public static void main(String[] args)
 2     {
 3         System.out.println("Thread 1\t\tThread 2\t\tBalance");
 4         
 5         ExecutorService executor = Executors.newFixedThreadPool(2);
 6         executor.execute(new DepositTask());
 7         executor.execute(new WithdrawTask());
 8         executor.shutdown();
 9     }
10     
11     
12     public static class DepositTask implements Runnable
13     {
14         public void run()
15         {
16             try
17             {
18                 while(true)
19                 {
20                     account.deposit((int)(Math.random() * 10) + 1);
21                     Thread.sleep(1000);
22                 }
23             }
24             catch(InterruptedException ex)
25             {
26                 ex.printStackTrace();
27             }
28         }
29     }
30     
31     public static class WithdrawTask implements Runnable
32     {
33         public void run()
34         {
35             while(true)
36             {
37                 account.withdraw((int)(Math.random() * 10) + 1);
38             }
39         }
40     }

 

四.客户端/服务器的网络应用

    Java中对socket的使用十分方便,在建立socket连接后就可以使用输入输出流的方法实现数据传输了。

    在实现基本的GUI后,在服务器用一个判断条件永远为true的循环来监听客户端的连接请求(Socket socket = serverSocket.accept();

    服务器通过创建一个内部类(HandleAClient),把客服端的socket传递过来执行。

HandleAClient类
 1     class HandleAClient implements Runnable
 2     {
 3         //A connected socket
 4         private Socket socket;
 5         
 6         /**Construct a thread */
 7         public HandleAClient(Socket socket)
 8         {
 9             this.socket = socket;
10         }
11         
12         /**Run a thread */
13         public void run()
14         {
15             try
16             {
17                 //Create data input and output streams
18                 DataInputStream inputFromClient = new DataInputStream(
19                         socket.getInputStream());
20                 DataOutputStream outputToClient = new DataOutputStream(
21                         socket.getOutputStream());
22                 int order = 0;
23                 double amount;
24                 //Continuously serve the client
25                 while(order != 4)
26                 {
27                     //Receive order, amount from the client
28                     order = inputFromClient.readInt();
29                     amount = inputFromClient.readDouble();
30                     
31                     if(order == 1)
32                     {
33                         outputToClient.writeDouble(account.getBalance());
34                     }
35                     else if(order == 2)
36                     {
37                         account.withdraw(amount);
38                         outputToClient.writeDouble(account.getBalance());
39                     }
40                     else if(order == 3)
41                     {
42                         account.deposit(amount);
43                         outputToClient.writeDouble(account.getBalance());
44                     }
45                     
46                     jta.append("Order received from client: "+
47                             order + '\n');
48                     jta.append("Balance is " + account.getBalance() + '\n');
49                 }
50             }
51             catch(IOException e)
52             {
53                 System.err.println(e);
54             }
55         }
56     }

    而客户端连接上服务器后,创建两个IO流

    //IO streams
    DataOutputStream toServer = new DataOutputStream(socket.getOutputStream());

    DataInputStream fromServer = new DataInputStream(socket.getInputStream());

  即可传输order(菜单选项)和amount

    //Send the order, amount to the server
    toServer.writeInt(order);
    toServer.writeDouble(amount);
    toServer.flush();

   最后再读取balance

   balance = fromServer.readDouble();

 

 

posted @ 2012-12-18 13:38  Edward@CS  阅读(1801)  评论(0编辑  收藏  举报