Java多线程编程-使用线程的缺点
1、初始启动变慢
在某些平台上创建和启动新线程是相对较慢的操作,在性能至上的应用程序中,这可能是很大的缺点。不过,线程池技术为这类问题提供了简单的解决方案,执行很多并发操作的应用程序通常会使用线程池,尤其是当应用程序操作的完成速度较快时更适合使用线程池。线程池的概念类似数据库连接池。
2、资源利用
每个线程都需要分配自身的栈,栈就是包含变量值和其他执行信息的存储区。除了栈之外,线程还要使用 其他系统资源,但不同JVM中所用的资源数量和类型也各不相同。虽然有时需要创建大量的线程,但所用平台可能会限制创建线程的数量。即使所有平台没有显式限制所能创建的线程数量,但一般根据处理器速度和系统可用内存也会有所限制。
这个问题虽然无法消除,但可以通过线程池技术得到控制。使用线程池除了你能消除创建新线程占用的系统开销外,还能够减少线程的创建数量。当然,要假定应用程序允许线程池管理器来控制创建线程的时刻以及创建线程的数量。Java中并未实现线程池管理器。
3、复杂性增加
显然,在应用程序中使用线程的最大缺点是它会增加复杂性。例如,调试单线程应用程序时很容易观察应用程序的执行流程,但多线程应用程序中就很难观察执行流程。
线程安全还往往关系到对象设计,线程在修改对象数据时,另一个对象就无法读写该数据。这里的数据指对象中封装的信息,一个数据项可能由对象的一个以上字段构成。
另一个更复杂的问题是多个线程间的资源共享。这里的资源指能够被多个线程同时访问的任意实体,大多数情况下您需要负责调配线程对资源的使用。例如,各种Swing组件本身都不是线程安全的,那么就要考虑如何调配应用程序的线程和AWT事件线程对Swing组件的使用。通常使用SwingUtilities类中的invokeAndWait()方法和invokeLate()方法,把对可视组件的修改委托给AWT事件线程。
资源共享的定义
在该方法中的定义的局部变量无法在方法外被访问,因而多个线程执行同一对象的该方法时无法共享该变量。例如,假设运行如下应用程序,其中创建两个线程使用同一个Runnable对象实例:
1 public class ThreadShare implements Runnable{ 2 3 public static void main(String[] args){ 4 ThreadShare ts = new ThreadShare(); 5 Thread t1 = new Thread(ts); 6 Thread t2 = new Thread(ts); 7 t1.start(); 8 t2.start(); 9 } 10 public void run(){ 11 int nonSharedValue = 100; 12 nonSharedValue += 100; 13 System.out.println("value:" + nonSharedValue); 14 } 15 }
由于nonSharedValue变量时在run()方法中定义的,因此它是方法的局部变量,无法被两个线程共享。则每个线程都会有各自的nonSharedValue副本,运行该应用程序产生的输出结果如下:
value: 200
value: 200
但如果修改应用程序使run()方法递增一个实例变量,则该变量为共享资源:
1 public class ThreadShare implements Runnable{ 2 3 int nonSharedValue = 100; 4 public static void main(String[] args){ 5 ThreadShare ts = new ThreadShare(); 6 Thread t1 = new Thread(ts); 7 Thread t2 = new Thread(ts); 8 t1.start(); 9 t2.start(); 10 } 11 public void run(){ 12 13 nonSharedValue += 100; 14 System.out.println("value:" + nonSharedValue); 15 } 16 }