Java多线程

一个进程调用多个线程
package com.company;

import java.awt.desktop.SystemEventListener;

public class threadtest extends Thread {

@Override
public void run() {
    System.out.println("yazoefan ");
}

public static void main(String[] args) {
    threadtest threadtest = new threadtest();
    threadtest.start();
    System.out.println("yazoefan2 ");
}

}

线程开启不一定立即执行,由CPU调度执行。
要调用start方法,不能调用run方法。

继承Thread类
子类继承Thread类具备多线程能力
启动线程:子类对象.start()
不建议使用:避免oop单继承局限性
public class threadtest extends Thread {

@Override
public void run() {
    System.out.println("yazoefan ");
}

public static void main(String[] args) {
    threadtest threadtest = new threadtest();
    threadtest.start();
    System.out.println("yazoefan ");
}

}

实现Runnable接口
实现接口Runnable具有多线程能力
启动线程:传入目标对象+Thread对象.start()
推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用
public class threadtest implements Runnable{

public void run() {
    System.out.println("yazoefan ");
}

public static void main(String[] args) {
    threadtest threadtest = new threadtest();
    new Thread(threadtest).start();
    System.out.println("yazoefan2 ");
}

}

//Lambda表达式

1、当代码行只有一行时,可以去掉花括号,但是有多行的话要加上花括号
2、前提是接口为函数式接口,指接口内只有一个方法
3、多个参数也可以去掉参数类型,要去掉都去掉,必须加上括号。

public class lamdaTest {
public static void main(String[] args) {
love loveyou = () ->{
System.out.println(“fuck you 颂长”);
};
loveyou.loveyou();
}
}

interface love{
void loveyou();
}

线程状态
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IBNFdfTd-1607159694391)(:storage\vq5uykitnk5a5rk9.png)]

//线程停止
public class ThreadStop implements Runnable {

private boolean flag =true;

@Override
public void run() {
    int i = 0;
    while (flag){
        System.out.println("fuck you"+i++);
    }
}

public void stop(){
    this.flag = false;
}

public static void main(String[] args) {
    ThreadStop threadStop = new ThreadStop();
    new Thread(threadStop).start();
    for (int i = 0; i < 1000; i++) {
        System.out.println("f"+i);
        if (i > 900){
            threadStop.stop();
            break;
        }
    }
}

}

//线程礼让
//让线程从运行状态变成就绪状态,让CPU重新调度
public class ThreadYield implements Runnable {

@Override
public void run() {
    System.out.println(Thread.currentThread().getName()+"start");
    Thread.yield();
    System.out.println(Thread.currentThread().getName()+"stop");
}

public static void main(String[] args) {
    ThreadYield threadYield = new ThreadYield();
    new Thread(threadYield,"a").start();
    new Thread(threadYield,"b").start();
}

}

//线程强制执行
//类似于插队,让其他线程阻塞
public class ThreadJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println(“I’m VIP”);
}
}

public static void main(String[] args) throws InterruptedException {
    ThreadJoin threadJoin = new ThreadJoin();
    Thread thread = new Thread(threadJoin);
    thread.start();
    for (int i = 0; i < 500; i++) {
        if (i == 50){
                thread.join();
            }
            System.out.println(i);
        
    }
}

}

//线程优先级
线程的优先级范围为1~10
数字越大优先级越高
优先级的设置最好是在start()调度前
public class ThreadPropotiy {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"–>"+Thread.currentThread().getPriority());
suger suger = new suger();
Thread t1 = new Thread(suger);
Thread t2 = new Thread(suger);
Thread t3 = new Thread(suger);
Thread t4 = new Thread(suger);
Thread t5 = new Thread(suger);

    t1.setPriority(10);
    t1.start();
    t2.setPriority(2);
    t2.start();
    t3.setPriority(3);
    t3.start();
    t4.setPriority(4);
    t4.start();
    t5.setPriority(5);
    t5.start();
}

}

class suger implements Runnable{

@Override
public void run() {
    System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}

}

//守护线程
线程分为用户线程和守护线程
虚拟机必须确保用户线程执行完毕
虚拟机不用等待守护线程执行完毕
public class ThreadPropotiy {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"–>"+Thread.currentThread().getPriority());
suger suger = new suger();
Thread t1 = new Thread(suger);
Thread t2 = new Thread(suger);
Thread t3 = new Thread(suger);
Thread t4 = new Thread(suger);
Thread t5 = new Thread(suger);

    t1.setPriority(10);
    t1.start();
    t2.setPriority(2);
    t2.start();
    t3.setPriority(3);
    t3.start();
    t4.setPriority(4);
    t4.start();
    t5.setPriority(5);
    t5.start();
}

}

class suger implements Runnable{

@Override
public void run() {
    System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}

}

//死锁
产生死锁的四个必要条件
1、互斥条件:一个资源每次只能被一个进程使用。
2、请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3、不剥夺条件:进程已获得的资源,在未使用完成之前,不能强行剥夺。
4、循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
public class deadlock {
public static void main(String[] args) {
Makeup makeup1 = new Makeup(0,“yao”);
Makeup makeup2 = new Makeup(1,“zheng”);

    new Thread(makeup1).start();
    new Thread(makeup2).start();

}

}
class Lipstick{
}

class Mirror{
}
class Makeup extends Thread {

static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();

int choice;
String girlname;

Makeup(int choice,String girlname) {
    this.choice = choice;
    this.girlname = girlname;
}
@Override
public void run() {
    try {
        makeup();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
private void makeup() throws InterruptedException {
    if (choice == 0){
        synchronized (lipstick){
            System.out.println("lipstick");
            Thread.sleep(1000);
            synchronized (mirror){
                System.out.println("mirror");
            }
        }
    }else{
        synchronized (mirror){
            System.out.println("mirror");
            Thread.sleep(2000);
        synchronized (lipstick){
            System.out.println("lipstick");
            }
        }
    }


}

}

破坏死锁的方法:只要想办法破坏其中的任意一个或多个条件就能避免死锁发送。

lock锁
public class locktest {
public static void main(String[] args) {
TestLock locktest = new TestLock();
new Thread(locktest).start();
new Thread(locktest).start();
new Thread(locktest).start();
}
}

class TestLock implements Runnable{
int ticketNum = 10;
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true){
lock.lock();
try{
if (ticketNum > 0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(ticketNum–);
}else {
break;
}
}finally {
lock.unlock();
}

    }
}

}

synchronized与Lock的对比
1、Lock是显示锁(手动开启和关闭锁,需要注意关锁)synchronized是隐式锁,除了作用于自动释放
2、Lock只有代码块锁,synchronized有代码块锁和方法锁
3、使用Lock锁,JVM将花费较少的时间来调度线程,性能更好,并且具有更好的扩展性(提供更多的子类)
有限使用顺序:
Lock > 同步代码块(已经进入了方法体,分配了相应资源) >同步方法(在方法体之外)

//管程法
//生产者消费者问题
public class TestPC {

public static void main(String[] args) {
    SynContainer container = new SynContainer();
    new Productor(container).start();
    new Consumer(container).start();
}

}

//生产者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container){
this.container = container;
}

@Override
public void run() {
    for (int i = 0; i < 100; i++) {
        System.out.println("生产了"+i+"只鸡");
        try {
            container.push(new Chicken(i));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

}
//消费者
class Consumer extends Thread {
SynContainer container;
public Consumer(SynContainer container){
this.container = container;
}
//消费
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
System.out.println(“消费了—”+container.pop().id+“只鸡”);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

//产品
class Chicken{
int id;

public Chicken(int id) {
    this.id = id;
}

}

//缓冲区
class SynContainer{
//容器大小
Chicken[] chickens = new Chicken[10];
int count = 0;
//生产者放入产品
public synchronized void push(Chicken chicken) throws InterruptedException {
//容器满了,等待消费者消费
if(count == chickens.length){
this.wait();
}
//没有满,就丢入产品
chickens[count] = chicken;
count++;
//可以通知消费者消费了
this.notifyAll();
}
//消费者消费产品
public synchronized Chicken pop() throws InterruptedException {
//判断能否消费
if (count == 0){
//等待生产者生产
this.wait();
}

    count--;
    Chicken chicken = chickens[count];
    this.notifyAll();
    return chicken;

}

}

//信号灯法
public class TestPC2 {

public static void main(String[] args) {
    TV tv = new TV();
    new Player(tv).start();
    new Watcher(tv).start();
}

}

class Player extends Thread {
TV tv;
public Player(TV tv) {
this.tv = tv;
}

@Override
public void run() {
    for (int i = 0; i < 20; i++) {
        if (i%2==0){
            this.tv.play("铁甲小宝");
        }else {
            this.tv.play("百变小樱");
        }
    }
}

}

//消费者–》演员
class Watcher extends Thread{
TV tv;
public Watcher(TV tv) {
this.tv = tv;
}

@Override
public void run() {
    for (int i = 0; i < 20; i++) {
        tv.watch();
    }
}

}
//生产者–》观众
class TV{
//演员表演,观众等待
//观众观看,演员表演
String voice;
boolean flag = true;
//表演
public synchronized void play(String voice){
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(“演员表演了:”+voice);
//通知观众观看
this.notifyAll();
this.voice = voice;
this.flag = !this.flag;
}

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

}

//线程池
思路:提前创建多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁,实现重复利用。
好处:
提高响应速度(减少了创建新线程的时间)
降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
public class TestPool {
public static void main(String[] args) {
//创建服务,创建线程池子
//newFixedThreadPool:参数为:线程池大小
ExecutorService service = Executors.newFixedThreadPool(10);

    service.execute(new MyThread());
    service.execute(new MyThread());
    service.execute(new MyThread());
    service.execute(new MyThread());

    //关闭连接
    service.shutdown();

}

}

class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页