进程与线程的区别?--多线程与线程池
每个进程都是一个程序,进程之间相互独立。除分布式外,进程数据之间,内存是不共享的。
线程存在于进程之中,一个进程包括一个或多个线程,每个线程都是一条路径,线程之间共享数据。
多线程 |
优点:合理利用CPU资源,单线程独占CPU资源,浪费CPU资源。并且可以提高程序的运行效率
缺点:1、如果有大量的线程运行,会消耗大部分内存,会影响性能(可能会死机),CPU需要他们之间的切换。
2、线程运行可能会出现死锁、线程安全问题(修改操作时你要考虑使用synchronized、lock(接口)、volatile)
synchronized关键字能保证在该方法中只有一个线程进入。只有当该线程执行结束或者出现异常,才会自动释放锁。否则其他线程必须的等待该线程释放。并且synchronized关键字是可重入锁,即在执行的时候如果从一个同步方法跳到了另一个同步方法,该线程不会再去申请锁,因为它还没释放。并且该关键字是非公平锁,每当一个线程释放锁后,无法保证谁会抢到该锁。
Lock是一个接口,在使用锁的时候要在run()方法调用lock()方法。 切记不可再run()方法中声明Lock接口再调用lock(),这样每次都会生成新锁,无法锁住该方法。每次在最后调用unlock()方法来释放锁,因为它不会自动释放锁。不释放会造成死锁现象。也是可重入锁。默认是非公平锁,如果声明时调用带参构造为true时,将会变成公平锁。即等待时间最长的线程首先获得锁。在读写操作时,ReadWriteLock接口有readlock()/writelock()。读操作可以同时进行。写操作有锁时,读写操作都要等待。读操作时只有写操作等待。
volatile关键字可以保证数据的可见性。并不是锁。而且在使用的同时,要尽量保证它是一个标识符while(flag){}.其中flag可以是可见的。因为volatile无法保证原子性操作。该关键字可以保证对一个变量的写操作先行发生于后面对这个变量的读操作。
线程池 |
优点:可以减少创建与销毁线程的开销、可以规定池内最大线程数,避免过多资源竞争消耗内存。能更好的控制线程开启与回收并且能定时执行任务。
Executors 提供四种线程池:
Executors.newFixedThreadPool(个数):创建固定个数的线程池,超出的线程会在队列中等待,如有发生异常的线程,会自动创建一个新线程。
Executors.newSingleThreadExecutor():创建一个只有一个单一线程的线程池,保证执行有序性,如有发生异常的线程,会自动创建一个新线程。
Executors.newCachedThreadPool():创建一个缓存的线程池,如果有之前的线程可以使用,则使用,否则创建。休闲时间超过60秒的线程将被废弃。
Executors.newScheduledThreadPool(个数):此线程池支持定时及周期性执行任务的需求。