多线程的初步理解
浅谈对多线程的理解
1.什么是进程和什么又是线程???
进程是指运行中的应用程序,每个进程都有自己独立的地址空间;
线程是进程中执行运算的最小单位,一个进程中可以有多个线程。
2.多线程的集中实现方式
(1):继承thread类,thread类本质上还是实现了runnable接口的一个实例,启动线程的唯一方法就是通过thread类的start()方法,启动一个新的线程并执行run()方法,可以重写run()方法来实现自己定义的方法。
(2):实现runnable接口,在已经继承了一个类的时候,可以实现runnable接口。
-------------------------------------------------------------------------------------------------------
runnable和callable区别:
Runnable和Callable都代表那些要在不同的线程中执行的任务,runnable是从jdk1.0就有了,callable是在1.5后增加的,callable的call()方法可以返回值和抛出异常,而runnable中的run()方法没有这些功能。
-------------------------------------------------------------------------------------------------------
(3):实现callable接口通过future task包装器来创建thread线程
3.多线程中的忙循环是什么
忙循环就是程序员创建的一个空循环,让线程进行等待,不同于wait(),sleep()他们都放弃了CPU控制,目的是为了保留CPU缓存,在多核系统中,一个线程醒来的时候可能会在另一个内核运行,这样会重建缓存,为了避免重建缓存和减少等待重建的时间。
4.进程之间如何进行通信
(1):管道(pipe)-----半双工通信模式,数据只能单向流动
(2):消息队列(messagequeue)-----消息队列里有消息的链表,存放在内核中并由消息队列标识符标识,消息队列克服了信号传递消息少,管道只能承载无格式字节流以及缓冲区大小受限。
(3):套接字(socket)-----可以用于不同进程间的通信
(4):共享内存(shared memory)-----映射一段能被其他进程访问的内存,这段内存由一个进程创建但多个进程都可以访问。
(5)信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生
5.线程间如何通信
(1):锁机制:包括互斥锁,读写锁,条件变量
1.互斥锁---提供了以排他方式防止数据结构被并发修改的方法
2.读写锁---允许多个线程同时读取共享数据,而对写操作是互斥的
3.条件变量---条件变量可以以原子的方式阻塞进程,知道某个特定条件为真为止,对条件的测试是在互斥锁的保护下进行的,条件变量始终与互斥锁一起使用
(2):信号量机制:包括无名线程信号量和命名线程信号量
(3):信号机制:类似进程间的信号处理
6.同步和异步有何不同,在什么情况下分别使用它们?
(1):如果数据将在线程间共享,必须使用同步存取
(2):如果应用程序在对象上调用了一个需要花费长时间执行的方法并且不需要让程序等待方法返回的时候,就应该使用异步编程。
同步交互---指发送一个请求,需要等待返回才能发送下一个请求
异步交互---指发送一个请求,不需要等待返回随时可以发送下一个请求
7.Hashtable与Hashmap的区别
hashtable与hashmap都实现了map接口
(1):在hashtable中,无论是key还是value都不能为null
(2):在hashmap中,null可以作为主键,这样的键只能有一个,但可以有一个或者多个键所对应的值为null,在使用get()方法返回的时候,既可以表示hashmap中没有该键亦可以表示该键的值为null,索引在hashmap中判断某个键是否存在的时候,不能使用get()方法,应该使用containsKey()方法。
hashmap与hashtable最大的不同是hashmap是线程不安全的,在多线程环境下,需要手动实现同步机制,hashtable是线程安全的,方法是同步的,可直接用于多线程环境中。
8.ConcurrentHashMap 和 Hashtable的区别
(1):ConcurrentHashMap是设计为非阻塞的,在更新时会局部锁住某部分数据,但不会把整个表都锁住,同步处理则是完全非阻塞的,好处在保证合理的同步下效率很高,坏处是读取操作时不能及时反映最近的更新。
(2):Hashtable的任何操作都会把整个表锁住,是阻塞的,好处是总能获取最新的数据(比如:当线程A在进行putAll()写入大量数据时,期间B正在get(),线程B就会被阻塞直到A写入完成)坏处是:效率低需要进行排队。
9.ArrayBlockingQueue的用法
一个线程向一个固定大小的队列里面不停的存放数据,另一个线程不停地向这个队列里面取数据,当队列满了,还继续存放数据,则此时出现阻塞,直到队列有空闲的位置;反之,当这个队列为空时,还继续取数据,也会出现阻塞,直到队列中有数据为止。
10.什么是线程安全的
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果都是一样的,而且其他变量的值也和预期的是一样的,就是线程安全的。
11.java中如何停止一个线程
Java没有为停止线程提供API,JDK1.0本来里有一些stop()、suspend()和resume()的控制方法,但由于存在潜在的死锁现象,在后来被弃用了,之后就没有提供一个兼容且线程安全的方法来停止一个线程。如果要手动结束一个线程,可以使用volatile布尔变量来退出run()方法的循环。
12.锁池和等待池
(1):锁池----假设A线程拥有了某个对象的锁,而其他线程想要执行这个对象的某个synchronized方法,由于没有该对象的锁的拥有权,这个线程就进入了该对象的锁池中。
(2):等待池----假设A线程调用了某个对象的wait()方法,线程A就会释放该对象的锁后进入到该对象的等待池中。
13.java中的wait和notifyall有什么区别?
(1):如果线程调用了对象的wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁
(2):当有线程调用了对象的notifyall(唤醒所有wait线程)或者notify(随机唤醒一个线程),被唤醒的线程就会进入到该对象的锁池中去,锁池中的线程会去竞争该对象锁。notify可能会产生死锁