java 面试复习 2
Thread
多线程创建: 方式一: 继承 Thread 类
结果:多线程交互
如果把 t1.start()改为 t1.run()
不用 start()后,其实没有创造新的 Thread, 只是调用了方法而已
不管 run 几次,都是分明的两个线程,而不是新建一个多线程
再启动一个线程遍历
不可以让已经执行 start()的线程去执行,会报 IllegalThreadStateException
再启动新线程,需要新一个对象
练习: 创建两个分线程,其中一个线程遍历 100 以内的偶数,另一个遍历 100 以内的奇数
可以用更简洁的方式创建,匿名子类
static void yield()
join() :在线程 a 中调用线程 b 的 join(),此时线程 a 就进入阻塞状态,直到线程 b 完成执行完以后,线程 a 才借宿阻塞状态
static void sleep(long millis)
stop()
boolean isAlive()
(setName():除了在主线程中运用 setName 外,)可以直接用带 name 的参数的构造器创建线程
线程优先级
设置优先级比较高,只是概率上执行起来高,而不能百分百保证先执行。
h1.setPriority(Thread.MAX_PRIORITY);
线程练习:卖票(认识存在安全问题)
private static int ticket = 100;
线程不安全的体现
创建线程第二种方法 Runable
线程练习:卖票(认识存在安全问题)
private int ticket = 100;
线程创建两种方式对比: extends Thread 和 implement runnable
-
因为有类的单继承的局限性,所以优先选择 implement runnable
-
实现的方式更适合来护理多个线程有共享数据的情况
联系:public class Thread implents Runnable,他们都需要重写 run()
线程安全问题
当一个线程 a 在操作 ticket 的时候,其他线程不能参与进来,知道线程 a 操作完成 ticket 时候
其他线程才可以开始操作 ticket,这种情况即使线程 a 出现阻塞,也不能被改编
-
方法一: synchronized
synchronized(同步监视器) { 需要被同步的代码 }
说明: 1.操作共享数据的代码,极为需要被同步的代码 2. 共享数据: 多个线程共同操作的变量: ticket 3. 同步监视器,可以是任何类的对象
解决了线程安全问题, 只有一个线程参与,其他等待,效率低
synchronized (this), 可以用 this 来代替 obj,
而 extend thread 中,要慎用 this,可以用 synchronized (windows。class)这种话方法,
-
方法二: 同步方法
方式 2: 同步方法解决 Runnable 线程安全问题
方式 2: 同步方法解决 extend 线程安全问题
- 同步方法仍然设计到同步监视器,只是不需要我们显式的声明
- 非静态的同步方法,同步监视器是: this 静态同步方法,同步监视器是: 当前类本身
-
使用同步机制将单例模式的懒汉式改写为线程安全
但同步锁会增加锁竞争,带来系统性能开销,从而导致系统性能下降,因此这种方式也会降低单例模式的性能。
此方法效率稍差:
此方法效率高的方法: