1.什么是多线程

线程就是进程中实际运行的单位,一个进程至少有一个线程

在java中默认有两个线程,一个是主线程(main),一个是GC线程(垃圾回收线程)

2.线程的六种状态

NEW:已经建立尚未启动的线程
RUNNABLE:在执行中的线程
BLOCKED:阻塞
WAITING:等待(一直等待)Object.wait(),Thread.join():两个方法无参调用
TIMED_WAITING:超时等待,等待另一个线程到达指定时间的等待状态,Object.wait()和Thread.join(),Thread.sleep()的有参调用
TERMINATED:终止状态

3.线程开启的三种方式

1.通过继承Thread类
2.通过实现Runnable接口
3.通过callable接口(详情见8)

4.sleep()与wait()的区别

1.原理不同。wait()是Object类的方法,用于线程通信。sleep()是Thread的静态方法,用于控制流程,让线程睡觉
2.作用域不同。wait()用于同步代码块中,sleep随处可用。
3.对锁的处理不同。wait()时会把锁给释放了,而sleep()会与锁一起睡觉。

5.synchronized和lock的区别

1.synchronized是一个关键字,lock是juc中的一个方法
2.synchronized会自动释放锁,lock需要手动释放锁
3.synchronized 会当线程1获得锁并且阻塞的话,线程2会一直等待;Lock不一定会一直等待下去,可以尝试获得锁(tryLock()方法),获取不到,就不再等待。
4.synchronized不可判断,非公平锁。lock可判断,公平锁。

6.线程间通信(生产者消费者问题)

等待,业务,唤醒
synchronized 用的是 wait() 和notifyall()
Lock 用的是 Condition 下的 await()和signalAll() (注:signal() 也有妙用,在多个Condition时,可用于定向的唤醒
注:判断时用while,而不是if来解决虚假唤醒。

7.synchronized锁的对象问题

1.synchronized,不同的对象,锁不同,执行同步方法时,不互相干扰
2.static synchronized锁住的是类,类与对象的锁互不干扰
3.不同对象的锁互不干扰

8.实现Callable接口执行多线程

1.与Runnable接口实现的区别:有返回值,方法不同,Runnable是run()
Callable是call(),可以声明抛出异常。
2.实现过程:FatureTask实现了Runnable接口,而FatureTask的构造器中需要传入Callable的对象,这样,将FatureTask传入Thread时,便将Callable和Thread联系起来了

MyThread myThread = new MyThread();

        FutureTask futureTask = new FutureTask(myThread);

        new Thread(futureTask).start();

9.线程池

1.作用

每次都要进行线程的开启和关闭十分占用资源,采用池化技术,将准备好的资源提前放入一个池子中,要使用时直接拿出来用
1.降低资源的消耗
2.提高响应速度
3.管理方便

2.三大方法

Executors工具类有三个创建线程池的方法
1.newSingleThreadExecutor()单线程池
2.newFixedThreadExecutor()固定大小的线程池
3.newCathedThreadExecutor()最大数无限大(21亿)
线程池用完要 shutdown()

3.七大参数

1.corePoolSize:核心大小,在一般情况下,准备出来的线程数
2.maximumPoolSize:
最大线程数,在线程数量需求变大时,会逐渐的开启线程,直到最大线程的大小
3.keepAliveTime:存活时间
4.TimeUnit unit:时间单位
5.BlockingQueue workQueue:阻塞列队,用于达到最大线程数时,再需要线程则进入阻塞队列
6.ThreadFactory threadFactory:线程的创建工厂
7.RejectedExecutionHandler handler:拒绝策略

四大拒绝策略

1.ThreadPoolExecutor.AbortPolicy() 丢弃任务 并抛出RejectedExecutionException异常
2. DiscardPolicy() 也是丢弃任务,但是不抛出异常
3.CallerRunsPolicy() 在达到最大承载的时候,由调用线程处理该任务
4. DiscardOldestPolicy() 丢弃队列最前面的任务,然后重新尝试执行任务

JMM

1.java内存模型,是一个概念,约定

2.线程解锁前,必须把共享变量更新到主内存
线程加锁前,必须从主内存中读取最新值读到工作内存中
加锁和解锁的是同一把锁

3.

Java多种实现方法怎么知道调用哪一个 java怎么判断有几个线程_多线程

Volatile

1.保证可见性:可见性就是,共享数据的实时变化是对多个线程可见的,啥是可见的呢?共享数据变了,每个线程都知道他变了,立马能看到,这就是可见的
2.不能保证原子性(原子性是在执行任务的过程中,不能被打扰,也不能被分割)
3.不允许指令重排,利用内存屏障来实现
保证特定操作的执行顺序
保证变量的内存可见性

java.util.concurrent.atomic

我们拿这个包下的类就来弥补volatile的不足,来保证原子性 我们拿AtomicInteger来举个例子。其本质是利用了CPU级别的CAS指令。由于是CPU级别的指令,其开销比需要操作系统参与的锁的开销小,它属于乐观指令,不会加锁。