多线程学习

1、start()和run()的区别
start()才是真正意义的实现了多线程,因为start会让线程处于就绪状态,不用等run运行结束就可以继续运行下面的代码,而如果直接调用run就是普通的方法调用,程序是顺序执行的

2、用哪个方法创建线程好点
java只能单继承却能多实现,所以如果想要再继承别的类,那就要选择实现Runnable接口方式

3、Callable和Runnable区别
Callable可以返回值和抛出异常
具体实现是
//Callable是泛型接口
public class Test implements Callable<String> {


public static void main(String[] args)throws ExecutionException, InterruptedException {
//创建callable对象
Callable<String> callable = new Test();
//创建FutureTask对象,同于获取返回结果
FutureTask<String> task = new FutureTask<>(callable);

//futuretask是runnable的实现类,所以可以作为参数创建线程
new Thread(task).start();
// 调用get()阻塞主线程,并得到返回结果
String result = task.get();
System.out.println("hello : " + result);

}

@Override
public String call() throws Exception {
Thread.sleep(1000);
return "lalala";
}
}

4、竞态条件:
两个或多个进程或线程对共享的数据进行读或写的操作时,最终的结果取决于这些进程或线程的执行顺序。一般产生竞态条件意味着线程不安全

5、为什么wait和notify方法要在同步块中使用?
因为不这样做会抛出异常,还有为了避免产生竞态条件

6、栈和堆的区别
栈用于存放局部变量,主要用来执行程序,存取速度快,大小和生存期必须确定,缺乏灵活性
堆用于存放类变量和new创建的实例变量,主要用于存放对象,存取速度慢,可以运行时动态分配内存,生存期不需要提前确定

7、volative和const,strictfp
volatile的变量是说这变量可能会被意想不到地改变
const是保留字,常量的意思,保留字就是现在还没用,将来的升级版本可能升级作为关键字
strictfp关键字可应用于类、接口、方法,指所有的float,double严格遵循FP-strict的规范

8、线程池
ThreadPoolExecutor创建线程需要花费资源和时间,线程池可以在程序启动的时候就创建若干线程来响应处理,这就称为线程池

9、LinkedBlockingQueue
是一个单向链表实现的阻塞队列,先进先出的顺序。支持多线程并发操作。
put()向队列尾部插入元素
peek()获取但不移除此队列的头,空返回null
poll()获取并移除此队列的头,空返回null
clear()移除所有元素
take()获取并移除此队列的头,在元素可用前一直等待

10、线程安全就是多个线程同时运行这段代码,而且运行结果跟单线程运行结果一样
集合中vector,LinkedList,hashtable,是线程安全的

11、怎么让线程停止
用isInterrupted()判断是否是中断位是否为true
用interrupt()设置中断位为true

12、产生死锁的条件
(1)互斥:一个资源每次只能被一个线程使用
(2)请求与保持:一个线程因请求资源而阻塞,对已获得的资源保持不放
(3)不剥夺:对于别人已得的资源,不能强行剥夺
(4)循环等待:多个线程间形成头尾相接的循环等待资源的关系

如何解决:
阻止循环等待最简单,按顺序加锁,给锁人为的安排一个顺序,只有在持有前面的锁的线程才能持有后面的锁

13、线程间的通信如何实现,最基本的就是利用多个对象的

归纳为睡锁在外,醒锁在内,用睡对象睡自己,叫醒醒对象所睡的

例子
public class Test implements Runnable {

private String name;
private Object prev;
private Object self;

private Test(String name, Object prev, Object self) {
this.name = name;
this.prev = prev;
this.self = self;
}

@Override
public void run() {
int count = 10;
while (count > 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
count--;
self.notify();
}
try {
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();

//每个线程都需要2个对象来构成2个行为,一个对象负责叫醒下一个线程,一个对象负责让本线程睡眠,所以有多少个线程就需要多少个Object
Test pa = new Test("A",c, a);
Test pb = new Test("B", a, b);
Test pc = new Test("C", b, c);

new Thread(pa).start();
Thread.sleep(100); //确保按顺序A、B、C执行
new Thread(pb).start();
Thread.sleep(100);
new Thread(pc).start();
Thread.sleep(100);

}
}

 

posted @ 2017-10-14 14:59  神芝  阅读(100)  评论(0编辑  收藏  举报