zoukankan      html  css  js  c++  java
  • 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();

  • 相关阅读:
    php之基础深入---类与对象篇
    php之cURL惯用
    php之header的不同用法
    java的图形界面初学惯用
    java 的http请求方式:HttpURLConnection和HttpClient
    数据挖掘-推荐算法入门
    性能测试平台效率优化的一次经验(python版)
    AndroidTest工程的自定义gradle task
    Robotium源码解读-native控件/webview元素的获取和操作
    工作中一些环境问题解决记录
  • 原文地址:https://www.cnblogs.com/edwardstudy/p/2822792.html
Copyright © 2011-2022 走看看