# 线程
## 进程和线程
### 进程介绍:

### 线程Thread介绍:
进程可以同时执行多个任务,每个任务就是线程:
### 多线程的作用:
提升执行效率,使更多进程可以并行执行
服务器必须用多线程
## Java中开启线程的方式:
### 1:继承Thread类:
案例:
```Java
public static void main(String[] args) {
/*
* 继承Thread类
* 重写run方法
* 将线程任务代码写在run方法
* 创建对象
* 对象名.start开启线程
* 只有调用start方法才会开启一个新线程
*/
Demo d1 = new Demo();
Demo d2 = new Demo();
d1.start();
d2.start();
}
}
class Demo extends Thread {
@Override
public void run() {
for (int i = 1; i <= 200; i++) {
System.out.println("打印了" + i);
}
}
}
```
### 注意:

### 2:实现Runnable接口
```java
/*
方法2 实现runnable接口
编写一个类实现接口
重写run方法
创建线程任务资源(就是创建对象)
然后创建线程对象,将任务资源传入,走构造方法
使用线程对象调用start方法
*/
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
Thread tr = new Thread(mr);
tr.start();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("八奈见杏菜");
}
}
```
### 3:实现Callable接口(有结果返回)
```java
public class ThreadDemo3 {
public static void main(String[] args) throws Exception {
/*
创建一个类实现Callable接口
重写call方法
创建线程任务资源对象
创建线程任务对象,封装线程任务资源(FutureTask)
创建线程对象传入线程任务
使用线程对象调用start方法开启线程
*/
MyCallAble mc = new MyCallAble();
FutureTask ft = new FutureTask<>(mc);
Thread t = new Thread(ft);
t.start();
Integer result = ft.get();
System.out.println(result);
}
}
class MyCallAble implements Callable{
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}
```
### 尽量选择后两个,拓展性更好
## 线程的方法

### 名字相关:

### 休眠线程:
### 线程调度方法:
Java是抢占式调度
### 守护线程
`final void setDaemon(boolean on );`
如图代码所示,t2守护t1,t1线程任务结束,t2也结束(不是立刻结束,t2会在苟活一会儿)
哪个线程对象调用setDaemon方法,这个线程就是守护线程
## 线程的安全与同步
### 1.同步代码块:

**使用同步代码块指定锁对象时,用类的字节码对象**
**共享数据要用static修饰**
### 2.同步方法:
### 3.Lock锁:
```Java
public static void main(String[] args) {
TicketShop1 ts = new TicketShop1();
Thread t1 = new Thread(ts);
Thread t2 = new Thread(ts);
Thread t3 = new Thread(ts);
t1.start();
t2.start();
t3.start();
}
}
class TicketShop1 implements Runnable{
private int ticket = 100;
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true){
//上锁
try {
lock.lock();
if (ticket == 0){
break;
}
System.out.println("卖出了"+ticket+"号票");
ticket--;
} finally {
//记得关闭锁
lock.unlock();
}
}
}
}
```
附加知识点:死锁:
## 线程通信
### 两条线程交替执行案例:
```Java
public static void main(String[] args) {
Print p = new Print();
Thread t1= new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (Print.class) {
try {
p.print1();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (Print.class) {
try {
p.print2();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
});
t2.start();
}
}
class Print{
private int flag = 1;
public void print1() throws InterruptedException {
if (flag != 1){
//wait只能通过锁对象进行调用
Print.class.wait();
}
System.out.print("八");
System.out.print("奈");
System.out.print("见");
System.out.print("杏");
System.out.print("菜");
System.out.println();
flag = 2;
//notif拥有空唤醒的权利
Print.class.notify();
}
public void print2() throws InterruptedException {
if (flag != 2){
Print.class.wait();
}
System.out.print("温");
System.out.print("水");
System.out.print("佳");
System.out.print("树");
System.out.println();
flag = 1;
Print.class.notify();
}
}
```
### 注意事项:
### 若想提升效率,使用ReentrantLock实现同步,获取Condition对象
注意:第一次指定线程等待时,绑定了线程
### 三条线程交替执行案例:
```Java
public static void main(String[] args) {
Printer p = new Printer();
Thread t1= new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
p.print1();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
p.print2();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
t2.start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
p.print3();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}).start();
}
}
class Printer{
private int flag = 1;
ReentrantLock lock = new ReentrantLock();
//调用newCondition来获取条件对象以此来指定线程
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
public void print1() throws InterruptedException {
lock.lock();
if (flag != 1){
//第一次调用await方法时绑定了线程
c1.await();
}
System.out.print("八");
System.out.print("奈");
System.out.print("见");
System.out.print("杏");
System.out.print("菜");
System.out.println();
flag = 2;
c2.signal();
lock.unlock();
}
public void print2() throws InterruptedException {
lock.lock();
if (flag != 2){
c2.await();
}
System.out.print("温");
System.out.print("水");
System.out.print("佳");
System.out.print("树");
System.out.println();
flag = 3;
c3.signal();
lock.unlock();
}
public void print3() throws InterruptedException {
lock.lock();
if (flag != 3){
c3.await();
}
System.out.print("温");
System.out.print("水");
System.out.print("梦");
System.out.print("子");
System.out.println();
flag = 1;
c1.signal();
lock.unlock();
}
}
```
### 生产者消费者模式:
### 生产者消费者案例:
## 线程生命周期:
## 线程池:
重点:自定义线程池
**拒绝策略**:用的最多的只有第一种AbortPolicy

**任务队列:**
### 总结:
### 案例:
```Java
public class Demo3 {
public static void main(String[] args) {
ThreadPoolExecutor tp = new ThreadPoolExecutor(
3,//核心数
6,//最大核心数
10,//空闲时间
TimeUnit.SECONDS,//时间单位
new ArrayBlockingQueue<>(10),//排队人数
Executors.defaultThreadFactory(),//线程对象任务工厂,基本为固定
new ThreadPoolExecutor.AbortPolicy()//拒绝策略,基本只用这个方法
);
for (int i = 1; i <17 ; i++) {
tp.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "调用了hhh");
}
});
}
tp.shutdown();
}
}
```
## 单例设计模式:
两种方式:
**饿汉式:简单不烧脑**:
直接创建出对象 而不是调用方法的时候再创建对象
**懒汉式:(延迟加载模式):**
