多线程基础

自己理解:

synchronized锁成员方法的时候 锁对象默认为该对象 如果锁的是静态方法 那锁对象为类
也就是synchronized修饰的方法 多个线程不能同时执行同一对象的该方法 但不同对象不会互斥 能同时执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Dog {
public synchronized void eat() throws InterruptedException {
System.out.println("eat start");
Thread.sleep(3000);
System.out.println("eat end");
}
}

public class MyRunnable implements Runnable{
public Dog dog;
public MyRunnable(Dog dog) {
this.dog = dog;
}
@Override
public void run() {
try {
dog.eat();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
Dog dog = new Dog();
Thread thread1 = new Thread(new MyRunnable(dog));
thread1.start();
Thread thread2 = new Thread(new MyRunnable(dog));
thread2.start();
}

输出
eat start
eat end
eat start
eat end

如果不用synchronized修饰 则并发输出eat start eat start 3秒后并发输出eat end eat end


Runnable接口与Callable接口的区别

同:都是接口。

异:
Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;

Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。


volatile和synchronized区别

volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。

但是volatile关键字只能用于变量,而synchronized关键字可以修饰方法、代码块

synchronized关键字在JavaSE1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁轻量级锁以及其它各种优化之后执行效率有了显著提升,实际开发中使用 synchronized 关键字的场景还是更多一些。

多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞

volatile关键字能保证数据的可见性,但不能保证数据的原子性。synchronized关键字两者都能保证。

volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized关键字解决的是多个线程之间访问资源的同步性。

synchronized 保证三大性:原子性,有序性,可见性,
volatile 保证有序性,可见性,不能保证原子性


提交任务时,线程池队列已满,会发生什么

如果使用的LinkedBlockingQueue,也就是无界队列的话,继续添加任务到阻塞队列中等待执行,因为LinkedBlockingQueue可以无限存放任务;
如果使用的是有界队列比方说ArrayBlockingQueue的话,则会使用拒绝策略RejectedExecutionHandler处理满了的任务


线程池中submit() 和 execute()方法有什么区别

两个方法都可以向线程池提交任务,
execute()方法的返回类型是void,它定义在Executor接口中, 而submit()方法可以返回持有计算结果的Future对象。


线程的调度策略

线程调度器选择优先级最高的线程运行,但是,如果发生以下情况,就会终止线程的运行:

(1)线程体中调用了 yield 方法让出了对 cpu 的占用权利

(2)线程体中调用了 sleep 方法使线程进入睡眠状态

(3)线程由于 IO 操作受到阻塞

(4)另外一个更高优先级线程出现

(5)在支持时间片的系统中,该线程的时间片用完


如何停止一个正在运行的线程?

使用退出标志(比如return),使线程正常退出,也就是当run方法完成后线程终止。
使用stop方法强行终止,但是不推荐这个方法,因为stop和suspend及resume一样都是过期作废的方法。
使用interrupt方法中断线程。