进程和线程
来源:互联网 发布:小狐仙软件 编辑:程序博客网 时间:2024/06/07 00:42
进程:
用jps 、ps-ef能看见的,就是进程。
程序启动之后,这个程序就是进程;但是有些程序会启动多个进程(像nginx)。
Jvm会为进程在内存中分配一个独立的运行空间
线程:
程序内部的一个独立的空间;在进程内部,再划分一些独立的空间。线程有自己的内存空间,就是有栈(存储局部变量,操作数)。线程在工作的时候本质就是调一些方法,我这个线程和另一个线程调用同一份代码,方法的代码只有一份,线程有两个实例在工作,这两个线程中的局部变量是不相同,在内存里面划分两片独立的空间,各自存自己的局部变量,但是两个线程运行的逻辑是同一份代码。QQ同时跟很多人聊天,就是很多的线程。图形化界面的程序,线程很多,类似word之类的。
传统Web服务,来一个用户请求,就开一个线程去响应他。线程的事情一般丢给Tomcat去做。
多线程:
就是在一个进程里面开启多个线程,让多个线程同时去完成某些任务。比如后台服务系统,就可以用多个线程同时响应多个客户请求。
为什么多个线程可以同时运行:
其实根本不可能同时运行,最多有cpu个同时运行,只是cpu切换很快而已。Cpu在线程之间切换。
Java实现线程的两种方法:
继承Thread;实现runnable()方法
public class MyThreadExtends extends Thread{String flag;public MyThreadExtends(String flag){this.flag = flag;}public void run(){String tname = Thread.currentThread().getName();System.out.println(tname + "线程run方法被调用了");Random random = new Random();for(int i = 0; i<20; i++){try {Thread.sleep(random.nextInt(10)*100);//sleep里面是毫秒System.out.println(tname+ "...."+ flag);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {Thread thread1 = new MyThreadExtends("a");Thread thread2 = new MyThreadExtends("b");//thread1.start();//thread2.start();//thread1.run();//thread2.run();//两种的区别,//run()这个是简单的调用,工作实在主线程中,主线程就 //在一个独立空间,变量什么的都在一个空间中。 //而start(),开启新的空间,在这个新的空间有自己的局部变量的一些//存储的地方,有自己的程序计数器,独立的去运行。 }}
public class MyThreadImpl implements Runnable{int x;public MyThreadImpl(int x){this.x = x;}public void run() {String tname = Thread.currentThread().getName();System.out.println(tname + "线程run方法被调用了");Random random = new Random();for(int i = 0; i<20; i++){try {Thread.sleep(random.nextInt(10)*100);//sleep里面是毫秒System.out.println(tname+ "...."+ x);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {Thread thread1 = new Thread(new MyThreadImpl(1),"thread1");//new Thread 然后传一个runnable的实现Thread thread2 = new Thread(new MyThreadImpl(2),"thread2");//thread1.start();//thread2.start();//thread1.run();//thread2.run();}}
同步锁synchronized:
(java的关键字)同样的代码块,不通的线程,只能有一个线程执行。解决共享数据冲突
伪代码:
synchronized( 需要任意一个对象(锁) )
{
代码块中放操作共享数据的代码;
}
缺陷:
(1)同步代码块里面,发生异常,jvm会释放这个锁,让其他线程享有。
(2)获取锁的线程执行完代码块,然后才释放对锁的占有
(3)降低效率,会等待很长时间
Lock:
(是类)可以不让等待的线程一直无期限的等待下去。比较:Synchronized 不需要用户手动释放锁,当synchronized代码块执行完后,系统会自动释放对锁的占用。Lock需要用户去手动释放锁。lock接口中的方法:
Public interface Lock{ void lock(); void lockInterruptibly() throw InterruptedException;//等待的人可以中断,就是说可以不用等了,可以去做其他事情了 boolean trylock();//尝试获取锁,可以不用等待,可以做一些异步的功能 boolean trylock(long Time,TimeUnit unit) throw InterruptedException;//尝试过程可以设置等待时间 void unlock();}
读写锁(ReadWriteLock):
读操作是可以并行读的;然而写操作才可能产生冲突,我写的时候,你就不能读了,你也就更不能写了。如果大家都拿到的是读的锁,那大家可以同时进行都操作,但是如果其中有一个人拿到了写操作的时候,其他人就不能读也不能写。
ReadWriteLock接口中的方法:
Public interface ReadWriteLock{ Lock readLock(); Lock writeLock();}
Lock和synchronized选择:
1、Lock是接口,而synchronized是关键字,synchronized是内置的语言实现
2、Synchronized在发生异常的时候,会自动释放锁,所以不会产生死锁的现象。而Lock发生异常的时候,如果没有主动unlock释放锁,就会造成死锁现象,因此使用lock的时候,一定要在finally里面进行unlock。
3、Lock可以让等待的线程中断,而synchronized却不行,使用synchronized时,等待线程会一直等待下去,不能响应中断。
4、通过Lock可以知道有没有获取锁,但是synchronized不行。
5、Lock可以提高多线程进行读操作效率。
在性能上来说,如果竞争不激烈的时候,两则性能差不多,但是竞争激烈的时候,此时lock优于synchronized。
上述总结:
实际生产环境中,不会new Thread().start(); 来一个客户端就产生一个线程,当请求量大的时候,超过了系统内存承受能力时候,并且线程多了,cpu需要在线程之间做轮询,也损耗资源,影响机器的性能和稳定性。所以就有了线程池。线程池:
一定线程数量,根据需要改变run方法进行不通逻辑的实现。线程池可以做成固定大小的,也可以做成弹性伸缩的。线程池实质就是一个数组或者时Array或者LinkList,把线程事先new好放进去。
线程池的经验之谈:
线程池在单机版的时候有用,在分布式的时候就不管用了,比如:抢购系统,需要高的响应速度,但是操作数据库库存又是很慢的操作,所以当用户请求的时候,会等很久得不到反应。所以此时可以这么做,把用户的请求丢到队列里面,相当于放到内存里面,然后返回一个等待页面给用户,这里实现了异步解耦,用户收到等待消息,然后服务器就自己去从队列里面取出请求,然后进行处理。这样看起来好像可以,但是一个公司抢购的业务往往不止一个,可能有10多个,20多个,甚至更多,并且都是几千万几千万的并发,那就会导致内存爆炸,这个时候就需要开启另外一台服务器,专门做消息队列的(JMS)。
线程池在java.util.concurrent包里面。
在这个包里面,有5中线程池创建方式:
1、Single Thread Executor:只有一个线程的线程池
代码:Executors.newSingleThreadExecutor()
2、Cached Thread Pool:线程池里面有很多线程看同时执行的,老的线程会被新的任务触发重新执行,如果有一个线程超过60秒没有任务执行,那么将终止并从线程池中删除。
代码:Executors.newCacheThreadPool()
3、Fixed Thread Pool:固定数量的线程池,如果没有新任务,那么线程会一直等
代码:Executors.newFixedThreadPool(int size)
线程数量根cpu保持一致,跟任务类型有关(io密集型还是运算密集型),运算密集型,就设小一点。io密集型设置大一点,因为里面涉及到硬件底层的中断,阻塞,通知,cpu相对快,所以开多点线程,但是硬盘速度也是有限的,开再多的线程速度也是有限的,所以这时相对的。
Cpu数量获得: int CpuNums = RunTime.getRunTime().availableProcessors();
4、Scheduled Thread Pool:就是有世家规定,例如:把任务丢进去,我不让你马上执行,隔五分钟在执行或者每两分钟执行一次。
代码:Executors.newScheduledThreadPool()
5、Single Thread Scheduled Pool:只有一个线程
代码:Executors.newSingleThreadScheduledExecutor()
synchronized中notify和wait的一些知识:
Public void run(){ Synchronized(需要被锁的对象obj){ Obj.notify();//唤醒其他也在等待obj资源的线程,把obj交给这个线程,但是本线程并没有阻塞,而是继续执行 Obj.wait();//该线程释放cpu控制,释放obj的锁,该线程阻塞,等待被唤醒,那么此时另一个线程获得锁,继续执行 }}
- 进程和线程
- 关于进程和线程
- 进程和线程
- 进程和线程
- 小解进程和线程
- 进程和线程
- 理解进程和线程
- 进程和线程
- 进程和线程
- 进程和线程 编程
- 进程和线程
- 进程和线程
- 线程和进程
- 进程和线程编程
- 程序、进程和线程
- 进程和线程 区别
- 进程和线程编程
- 什么是线程和进程
- ServletConfig和ServletContext的简单使用
- 算法导论第三版第七章快速排序(一般和随机化版本)
- 【Scikit-Learn 中文文档】四十四:机器学习: scikit-learn 中的设置以及预估对象
- windows下常用的bat命令(备份数据库、自动删除等)
- 一篇真正教会你开发移动端页面的文章(一)
- 进程和线程
- INSTALL_HADOOP
- MRU
- Oracle数据类型和对应的java类型
- jQuery
- SwipeRefreshLayout下拉刷新上拉加载详解
- mac 升级到10.13,CocoaPods不能使用了。
- 软件工程视频学习——第六章——面向对象的分析和设计方法
- kotlin说:老兄(Swift)我们一起打江山!