线程

进程与线程的关系

  • 进程是执行一个程序操作系统会进行分配一个进程,如idea开启就会有一个进程,而进程里面会有很多线程,如酷狗音乐里面有播放器等。

  • 假如电脑只有一个cpu,也就是单核,那么多线程只是轮流执行,因为切换时间很快,因而让人无所察觉。

线程有三种实现方式(Thread,Runnable,Callable)

  1. Thread方式

    • 首先继承Thread

    • 重写run()

    • 开启线程start()

    public class thread1 extends Thread {
    @Override
    public void run() {
      for (int i = 0; i < 20; i++) {
          System.out.println("这是线程,正在打印"+i);
      }
    }

    public static void main(String[] args) {
      //创建一个线程
      thread1 thread1 = new thread1();
      //开启
      thread1.start();
      //主线程main的for
      for (int i = 0; i < 200; i++) {
          System.out.println("这是主线程,正在打印"+i);
      }

    }
    }
  2. Runnable方式

    • 首先实现Runnable

    • 重新run()

    • 创建Thread线程

    • 把Runnable实现的类传入Thread

    • 开启start()

    public class runable implements Runnable{
    public void run() {
      for (int i = 0; i < 20; i++) {
          System.out.println("这是Runnable,正在打印"+i);
      }
    }

    public static void main(String[] args) {
      //创建一个runnable类
      runable runable = new runable();
      //创建一个线程
      Thread thread = new Thread(runable);//代理模式
      //开启
      thread.start();
      //主线程main
      for (int i = 0; i < 200; i++) {
          System.out.println("这是主线程,正在打印"+i);
      }

    }
    }

小结:

  • Thread不建议使用:避免oop单继承局限性

  • Runnable推荐使用:灵活方便,方便同一个对象被多个线程使用

  1. Callable

    • 实现Callable接口

    • 重写call()

    • 创建实例

    • 创建线程服务Executors.newFixedThreadPool

    • 提交服务submit

    • 获取结果get()

    • 关闭服务shutdownNow()

    import java.util.concurrent.*;

    public class callable implements Callable<Boolean> {

    public Boolean call() throws Exception {
      for (int i = 0; i < 20; i++) {
          System.out.println("这是callable,正在打印"+i);
      }
      return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
      //创建callable实例
      callable callable1 = new callable();
      callable callable2 = new callable();
      //创建执行服务
      ExecutorService ser = Executors.newFixedThreadPool(2);//开启两个线程
      //提交执行
      Future<Boolean> submit = ser.submit(callable1);
      Future<Boolean> submit1 = ser.submit(callable2);
      //获取结果
      Boolean aBoolean = submit.get();
      Boolean aBoolean1 = submit1.get();
      System.out.println(aBoolean+","+aBoolean1);
      //关闭服务
      ser.shutdownNow();
    }
    }

静态代理

  1. 两个类必须实现同一个接口

  2. 一个实例传入另外一个实例,并调用实现接口的方法

public class staticProxy {
public static void main(String[] args) {
  You you = new You();
  //代理you
  MarryCompany marryCompany = new MarryCompany(you);
  marryCompany.HappyDay();
  //Thread也是一个代理,都是会实现implements Runnable
}
}

interface Marry{
void HappyDay();
}

class You implements Marry{
public void HappyDay() {
  System.out.println("今天结婚,好开心!!");
}
}

class MarryCompany implements Marry{
private Marry marry;
public MarryCompany(Marry marry){
  this.marry = marry;
}

public void HappyDay() {
  before();
  //调用
  marry.HappyDay();
  after();
}

private void after() {
  System.out.println("结婚后");
}

private void before() {
  System.out.println("结婚前");
}
}

lamda表达式

  1. 必须有一个接口而且只有一个抽象方法

public class lamda {
public static void main(String[] args) {
  //匿名函数
  my_lamda m = new my_lamda() {
      public void happy() {
          System.out.println("hello lamda");
      }
  };
  m.happy();
  //lamda表达式
  m = () -> {
      System.out.println("hello lamda2");
  };
  m.happy();
  //简化
  m = () -> System.out.println("hello lamda3");
  m.happy();
  //带有参数
  love love = (int a) ->{
      System.out.println(a);
  };
  love.love(520);
  //简化
  love = (a) -> System.out.println(a);
  love.love(521);
  //在简化
  love = a -> System.out.println(a);
  love.love(522);
  //带有两个参数
  love2 love2 = (int a,int b) ->{
      System.out.println(a+","+b);
  };
  love2.love2(520,521);
  //简化
  love2 = (a,b)->{System.out.println(a+","+b);};
  love2.love2(522,523);
}

}
//函数式
interface my_lamda{
void happy();
}
interface love{
void love(int a);
}

interface love2{
void love2(int a,int b);
}

方法

线程停止

  • stop()方法不建议使用,建议使用线程标志位来停止

public class TestStop {
public static void main(String[] args) {
  stop_test st = new stop_test();
  Thread thread = new Thread(st);
  //开启
  thread.start();
  //停止
  st.stop();
}
}

class  stop_test implements Runnable{
private boolean flag = true;
@Override
public void run() {
  while (flag){
      System.out.println("正在执行");
  }
}
public void stop(){
  this.flag = false;
}
}

sleep()

  • 每一个类都有一个锁,sleep()不会释放锁

import java.text.SimpleDateFormat;
import java.util.Date;
//模拟倒计时
public class TestSleep {
public static void main(String[] args) {
  sleep_test st = new sleep_test();
  Thread thread = new Thread(st);
  thread.start();
}
}
class sleep_test implements Runnable{
@Override
public void run() {
  for (int i = 0; i < 10; i++) {
      Date date = new Date(System.currentTimeMillis());//当前时间
      System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
      date = new Date(System.currentTimeMillis());
      try {
          Thread.sleep(1000);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
  }

}
}

yield()

  • 当前的线程暂停,但不阻塞,从运行状态到就绪状态,让cpu重新调度。

public class TestYield {
public static void main(String[] args) {
  yield_test yt = new yield_test();
  Thread thread = new Thread(yt,"a");
  Thread thread2 = new Thread(yt,"b");
  thread.start();
  thread2.start();
}
}

class yield_test implements Runnable{

@Override
public void run() {
  System.out.println(Thread.currentThread().getName()+":执行前");
  Thread.yield();
  System.out.println(Thread.currentThread().getName()+":执行完成");
}
}

join()

  • 让线程先执行,也就是插队

public class TestJoin {
public static void main(String[] args) {
join_test jt = new join_test();
Thread thread = new Thread(jt,"join");
thread.start();
for (int i = 0; i < 500; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
if(i == 100){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

class join_test implements Runnable{

@Override
public void run() {
for (int i = 0; i < 30; i++) {
System.out.println(Thread.currentThread().getName()+":在数"+i);
}
}
}

线程状态

public class ThreadState {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() ->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//创建
Thread.State state = t.getState();
System.out.println(state);
t.start();
//就绪
state = t.getState();
System.out.println(state);

while (state != Thread.State.TERMINATED){ //线程不死亡就监控
state = t.getState();
System.out.println(state);
Thread.sleep(100);
}
}
}

线程的优先级

  • setPriority(),getPriority()的范围为1~10,数字越大优先级越高

public class TestPriority {
public static void main(String[] args) {
Priority_test pt = new Priority_test();
Thread t1 = new Thread(pt,"a");
Thread t2 = new Thread(pt,"b");
Thread t3 = new Thread(pt,"c");
Thread t4 = new Thread(pt,"d");
t1.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.setPriority(Thread.MAX_PRIORITY);
t2.start();
t3.setPriority(3);
t3.start();
t4.setPriority(7);
t4.start();
System.out.println(Thread.currentThread().getPriority());
}
}

class Priority_test implements Runnable{

@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":线程的级别为"+Thread.currentThread().getPriority());
}
}

守护线程

  • daemon(true)

  • 用户线程一旦结束,守护线程就结束。

public class TestDaemon {
public static void main(String[] args) {
NewYou ny = new NewYou();
God god = new God();
Thread t2 = new Thread(god);
t2.setDaemon(true);
t2.start();

Thread t = new Thread(ny);
t.start();
}
}

class NewYou implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("我还活着");
}
}
}
class God implements Runnable{

@Override
public void run() {
while (true){
System.out.println("上帝守护着你");
}

}
}

线程同步

  • 保证了安全性,但是性能降低。

  • 同步就是队列和锁

  • sychronized同步方法和同步块

//买票(sychronized)
public class TestSynchronized {
public static void main(String[] args) {
ticket t = new ticket();
Thread thread = new Thread(t,"小明");
Thread thread1 = new Thread(t,"小红");
thread.start();
thread1.start();
}
}

class ticket implements Runnable{
private int tickets = 10;
private boolean flag = true;
@Override
public void run() {
while (flag){
buy();
}
}
private synchronized void buy(){
if(tickets<=0){
flag = false;
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"购买了第"+tickets--+"票");
}
}
//synchronized代码块
//注意要选择锁的资源
//相对与synchronized方法性能好,原因是锁定的资源少,而前者是整个方法
public class bank {
public static void main(String[] args) {
Account a = new Account(2000);
BankAto t1 = new BankAto(a,1000,0);
BankAto t2 = new BankAto(a,800,0);
t1.setName("小明");
t2.setName("小红");
t1.start();
t2.start();
}
}

class Account {
private float money = 0;
public Account(float money){
this.money = money;
}
public float getMoney(){
return money;
}
public void setMoney(float money){
this.money = money;
}
}

class BankAto extends Thread{
private Account account;
private float fetchMoney;
private float myMoney;

public BankAto(Account account,float fetchMoney,float myMoney){
this.account = account;
this.fetchMoney = fetchMoney;
this.myMoney = myMoney;
}
public void run(){
synchronized (account){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
fetch();
}
}

private void fetch(){
if(this.account.getMoney() < fetchMoney){
System.out.println(Thread.currentThread().getName()+":余额不足");
return;
}
this.account.setMoney(this.account.getMoney() - fetchMoney);
this.myMoney = this.myMoney + fetchMoney;
System.out.println(this.getName()+":手里的钱为"+this.myMoney);
System.out.println("卡里的钱为"+this.account.getMoney());
}
}
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;

public class list_synchronized {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 2000; i++) {
//不安全
// new Thread(()->{
// list.add(Thread.currentThread().getName());
// }).start();
//安全
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();

}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());

//JUC安全的list
CopyOnWriteArrayList<String> copyOnWriteArrayList = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 2000; i++) {
new Thread(()->{
copyOnWriteArrayList.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(copyOnWriteArrayList.size());
}
}

死锁

  • 多个线程需要对方需要的资源

//死锁
public class deathLock {
public static void main(String[] args) {
test_deathLock t = new test_deathLock(0);
test_deathLock t2 = new test_deathLock(1);
t.start();
t2.start();
}
}
class a{

}
class b{

}
class test_deathLock extends Thread{
static a a = new a();
static b b = new b();
private int select1;
public test_deathLock(int select1){
this.select1 = select1;
}
@Override
public void run() {
deathLick();
}

private void deathLick(){
if(select1 == 1){
synchronized (a){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+"获取a");
synchronized (b){
System.out.println(this.getName()+"获取b");
}
}
}else {
synchronized (b){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+"获取b");
synchronized (a){
System.out.println(this.getName()+"获取a");
}
}
}
}
}

Lock锁

  • 性能比synchronized好,但是synchronized可以用在方法上

import java.util.concurrent.locks.ReentrantLock;

public class testLock {
public static void main(String[] args) {
ticket2 t = new ticket2();
Thread t2 = new Thread(t,"小共");
Thread t3 = new Thread(t,"小红");
t2.start();
t3.start();
}
}

class ticket2 implements Runnable{
private int tickets = 10;
private boolean flag = true;
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (flag){
try {
lock.lock();
buy();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}

public void buy(){
if(tickets <= 0){
flag = false;
return;
}
System.out.println(Thread.currentThread().getName()+"购买了"+tickets--+"票");
}
}

线程协同

  • 是关于消费者和生产者之间的通信

  • wait()让线程等待,并让当前线程释放它持有的锁,直到notify()或notifyAll()让线程唤醒并进入就绪状态。

  • wait(long timeout)让线程等待一段时间,并让当前线程释放它持有的锁,直到notify()或notifyAll()或到指定时间让线程唤醒并进入就绪状态。

  • notify()是唤醒单个线程,notifyAll()是唤醒所有线程。

import java.util.ArrayList;

//管程法
//生产者 消费者 产品 缓存
public class TestXieCheng {
public static void main(String[] args) {
cache cache = new cache();

new Productor(cache).start();
new Consumer(cache).start();
}
}
//产品
class Product{
Integer id;
String name;
public Product(Integer id,String name){
this.id = id;
this.name = name;
}
}
//生产者
class Productor extends Thread{
cache cache;
public Productor(cache cache){
this.cache = cache;
}

public void run(){
//生产
for (int i = 0; i < 10; i++) {
cache.push(new Product(i+1,"罐头"));
}
}
}

//消费者
class Consumer extends Thread{
cache cache;
public Consumer(cache cache){
this.cache = cache;
}

public void run(){
for (int i = 0; i < 10; i++) {
//消费
cache.pop();
}
}
}

//缓存
class cache{
//存放产品
Product[] products = new Product[10];
Integer i = 0;
//生产者
public synchronized void push(Product product){
//是否仓库已满
if(i+1 == products.length){
//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products[i] = product;
System.out.println("生产了第"+product.id+"个"+product.name);
i++;
//告知消费者消费
this.notifyAll();
}
//消费者
public synchronized Product pop(){
//是否仓库为空
if(products.length == 0){
//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i--;
Product product = products[i];
System.out.println("消费了第"+product.id+"个"+product.name);
//通知生产者生产
this.notifyAll();
return product;
}
}
import java.util.ArrayList;
//信号灯法
public class TestXinHaoDeng {
public static void main(String[] args) {
TV tv = new TV();
new actor(tv).start();
new watcher(tv).start();
}
}

//演员
class actor extends Thread{
TV tv;
public actor(TV tv){
this.tv =tv;
}
public void run(){
for (int i = 0; i < 10; i++) {
if(i%2 == 0){
tv.performance("奥特曼上演了");
}else {
tv.performance("数鸭子");
}
}
}
}
//观众
class watcher extends Thread{
TV tv;
public watcher(TV tv){
this.tv =tv;
}
public void run(){
for (int i = 0; i < 10; i++) {
tv.watch();
}
}
}
//节目
class TV {
String programs;
//true就让演员表演节目
boolean flag = true;

//节目表演
public synchronized void performance(String programs){
if(!flag){
//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.programs = programs;
System.out.println("演员:表演了"+programs);
this.flag = !this.flag;
//通知观众看
this.notifyAll();
}
//节目观看
public synchronized void watch(){
if(flag){
//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观众:看了"+programs);
this.flag = !this.flag;
//通知演员表演
this.notifyAll();
}
}

线程池

  • execute()是执行Runnable接口的类,没有返回值,submit()是Callable接口的类,有返回值,但也可以执行Runnable接口的类。

  • 优点:

    • 提高响应的速度

    • 降低资源的消耗

    • 便于管理

      • corePoolSize: 核心池大小

      • maximumPoolSize: 最大线程数

      • keepAliveTime: 线程没有任务最大保持多长时间会终止

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestPool {

public static void main(String[] args) {
//创建线程池
ExecutorService service = Executors.newFixedThreadPool(10);

for (int i = 0; i < 10; i++) {
//execute是Runnable接口的,没有返回值
service.execute(new polltest());
}
//service.submit();这是有返回值,用get()可以获取返回值
//关闭
service.shutdown();
}
}

class polltest implements Runnable{

@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"测试Pool");
}
}

总结

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class TestCallable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
  //Thread
  myThread myThread = new myThread();
  myThread.start();
  //Runnable
  Thread thread = new Thread(()->{
      System.out.println("Runnable");
  });
  thread.start();
  //Callable
  FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
      @Override
      public String call() throws Exception {
          return "Callable";
      }
  });
  futureTask.run();
  System.out.println(futureTask.get());
}
}
class myThread extends Thread{
public void run(){
  System.out.println("Thread");
}
}