服务端代码优化方案(多线程)

1. 使用单例
对于 IO 处理、数据库连接、配置文件解析加载等一些非常耗费系统资源的操作, 我们必须对这些实例的创建进行限制, 或者是始终使用一个公用的实例, 以节约系统开销, 这种情况下就需要用到单例模式。

public class Singleton {    
   private volatile static Singleton singleton;    
   private Singleton (){}    
   public static Singleton getSingleton() {    
   if (singleton == null) {    
       synchronized (Singleton.class) {    
       if (singleton == null) {    
           singleton = new Singleton();    
       }    
       }    
   }    
   return singleton;    
   }    
}

2. 使用线程池
合理利用线程池能够带来三个好处。

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

Executor 框架便是 Java 5 中引入的,其内部使用了线程池机制,它在 java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。

public class MultiThreadTest {  
  public static void main(String[] args) {  
      ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("thread-%d").build();  
      ExecutorService executor = new ThreadPoolExecutor(2, 5, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);  
      executor.execute(new Runnable() {  
          @Override  
          public void run() {  
             System.out.println("hello world !");  
          }  
      });  
      System.out.println(" ===> main Thread! " );  
  }  
}

3. 使用 Future 模式
假设一个任务执行起来需要花费一些时间, 为了省去不必要的等待时间, 可以先获取一个“提货单”, 即 Future, 然后继续处理别的任务, 直到“货物”到达, 即任务执行完得到结果, 此时便可以用“提货单”进行提货, 即通过 Future 对象得到返回值。

public class RealData implements Callable<String> {    
   protected String data;    
  
   public RealData(String data) {    
       this.data = data;    
   }    
  
   @Override    
   public String call() throws Exception {    
       //利用sleep方法来表示真是业务是非常缓慢的    
       try {    
           Thread.sleep(1000);    
       } catch (InterruptedException e) {    
           e.printStackTrace();    
       }    
       return data;    
   }    
}    
  
public class Application {    
   public static void main(String[] args) throws Exception {    
       FutureTask<String> futureTask =     
               new FutureTask<String>(new RealData("name"));    
       ExecutorService executor =     
               Executors.newFixedThreadPool(1); //使用线程池    
       //执行FutureTask,相当于上例中的client.request("name")发送请求    
       executor.submit(futureTask);    
       //这里可以用一个sleep代替对其他业务逻辑的处理    
       //在处理这些业务逻辑过程中,RealData也正在创建,从而充分了利用等待时间    
       Thread.sleep(2000);    
       //使用真实数据    
       //如果call()没有执行完成依然会等待    
       System.out.println("数据=" + futureTask.get());    
   }    
}