java线程

1.进程和线程

1.1进程

进程是一个独立运作应用程序

1.独立性:

​ 各个进程之间是互相独立的,互相不影响的

2.互斥行:

​ 每个应用程序(软件)系统分配一个独立的端口号如果一个软件qq端口号 97 idea端口也叫97

写代码 Demo1 里面 main主函数 Demo1可以看成一个应用程序 就是一个进程

1.2线程

进程是由至少一个或者多个线程组成的

线程是进程最小的基本单位

线程的特性:

1.抢占式运行【重要】

​ 给程序 分配CPU,按照时间片来执行,单位时间片抢占式执行的。随机抢占的

2.资源共享

​ 同一个进程,有多个线程,这个多个线程是可以共享同一个数据的

​ Java程序:Demo1可以看成一个进程,

一个Java程序中有两个线程:

​ 1.main 主线程

​ 2.垃圾回收的线程

1.3并行和并发

并行:真正的同时执行

并发:同时发生,轮流交替执行

1.4创建线程的两种方式

Java虚拟机允许应用程序同时执行多个执行线程。

创建线程的第一种方式:( 继承Thread)

​ 创建一个新的执行线程有两种方法。 一个是将一个类声明为Thread的子类。 这个子类应该重写run方法Thread 。 然后可以分配并启动子类的实例。

//1.一个是将一个类声明为`Thread`的子类
class MyThread1 extends Thread {
    //2.重写run方法
    @Override
    public void run() {
        //这个线程中干了打印100次的MyThread1线程:
        for (int i = 0; i < 10000; i++) {
            System.out.println("MyThread1线程:" + i);
        }
    }
}
class MyThread2 extends  Thread {
    @Override
    public void run() {
        //这个线程中干了打印100次的MyThread2线程:
        for (int i = 0; i < 10000; i++) {
            System.out.println("MyThread2线程:" + i);
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        //3.新建线程的实例
        MyThread1 myThread1 = new MyThread1();
        //4.启动线程  启动
        myThread1.start();
        MyThread2 myThread2 = new MyThread2();
        myThread2.start();

        for (int i = 0; i < 10000; i++) {
            System.out.println("主线程" + i);
        }

    }
}

创建线程的第二种创建方式:(实现Runnable接口)

另一种方法来创建一个线程是声明实现类Runnable接口。 那个类然后实现了run方法。 然后可以分配类的实例,在创建Thread时作为参数传递,并启动。

//声明实现`Runnable`接口的类
class MyThread1 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("MyThread1:" + i);
        }
    }
}
class MyThread2 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("MyThread2:" + i);
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        MyThread1 myThread1 = new MyThread1();
        MyThread2 myThread2 = new MyThread2();
        //在创建`Thread`时作为参数传递并启动。
        new Thread(myThread1).start();
        new Thread(myThread2).start();
    }
}

新建两个线程,一个线程打印99乘法表,另外一个线程打印直接三角形

class MyThread3 implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i < 10 ; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
class MyThread4 implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print(j + "*" + i + "=" + i*j + "\t");
            }
            System.out.println();
        }
    }
}
public class Demo3 {
    public static void main(String[] args) {
        // 然后可以分配类的实例,在创建Thread时作为参数传递,并启动。
        new Thread(new MyThread3()).start();
        new Thread(new MyThread4()).start();
    }
}

1.5线程方法

构造方法:

Thread()

分配一个新的Thread对象 (第一种创建的形式)

Thread(Runnable target)

分配一个新的Thread对象 (第二种创建的形式)

Thread(Runnable target, String name)

分配一个新的Thread对象,并对这个线程起一个名字

方法:

static ThreadcurrentThread()返回对当前正在执行的线程对象的引用
StringgetName()返回此线程的名称
voidsetName(String name)将此线程的名称更改为等于参数name
class MyThread1 implements Runnable {
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        //Mythread1默认的额名字Thread-0
        System.out.println(thread.getName());
    }
}
class MyThread2 implements Runnable {
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        //Mythread1默认的额名字Thread-1
        System.out.println(thread.getName());
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();//获取当前线程对象
        System.out.println(thread.getName());//获取当前线程的名字   main
        Thread thread1 = new Thread(new MyThread1(), "二狗");
        //thread1.setName("狗蛋");
        thread1.start();
        new Thread(new MyThread2()).start();
    }
}

线程下面的方法:

intgetPriority()返回此线程的优先级
voidsetPriority(int newPriority)更改此线程的优先级
class MyThread3 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.println("优先级是1的:" + i);
        }
    }
}
class MyThread4 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.println("优先级是10的:" + i);
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getPriority());//获取当前线程的优先级   5
        Thread thread1 = new Thread(new MyThread3());
        thread1.setPriority(3);
        thread1.start();
        Thread thread2 = new Thread(new MyThread4());
        thread2.setPriority(6);
        thread2.start();
    }
}
static voidsleep(long millis)使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性
class MyThread3 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.println("优先级是1的:" + i);
        }
    }
}
class MyThread4 implements Runnable {

    @Override
    public void run()  {
        /**
         * 为啥  Thread.sleep(20000);   只能try-catche
         * run方法是重写的,重写的有严格限定
         * public abstract void run();
         *
         */
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 10000; i++) {
            System.out.println("优先级是10的:" + i);
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getPriority());//获取当前线程的优先级   5
        Thread thread1 = new Thread(new MyThread3());
        thread1.setPriority(3);
        thread1.start();
        Thread thread2 = new Thread(new MyThread4());
        thread2.setPriority(6);
        thread2.start();
    }
}

1.6线程同步和锁

当多个线程同时请求一个数据的时候,会导致数据不准确的情况。相互之间产生问题。容易出现线程安全的问题。

线程的同步真实的意思: 让你"排队",几个线程之间要排队。一个一个对共享资源进行操作,等一个结束以后,另外一个再进来操作。变量 是唯一的和准确的 可以加锁

同步方法:
	public synchronized void eat () {
	
	}
	只能有一个线程进入到方法中,其他线程在方法的外面等待
同步代码块:  将一段代码放到synchronized   然后括起来。就会对这段代码加上锁。
		synchronized (this) {
			
		}
class SaleTicket implements Runnable {
    private  int ticket = 100;
    @Override
    public  void run() {

        while (true) {

            synchronized (this) {

                if (ticket > 0) {

                    //线程2卖出了第72票
                    //线程2卖出了第71票
                    //线程1卖出了第100票
                    //线程1   线程2 都进入到if语句了
                    //
                    System.out.println(Thread.currentThread().getName() + "卖出了第" + ticket +"票");

                    ticket--;
                } else {
                    System.out.println("卖完了");
                    break;
                }
            }
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        //强调的是:多个线程操作同一个数据  ticket
        SaleTicket saleTicket = new SaleTicket();

        new Thread(saleTicket, "线程1").start();
        new Thread(saleTicket, "线程2").start();
    }
}

要求不能使用同步代码块来解锁,必须使用同步方法来加锁 来实现上面的案例

class SaleTicket1 implements Runnable {
    private  int ticket = 100;
    @Override
    public  void run() {

        while (true) {
                test();
                if (ticket <= 0) {
                    break;
                }

        }
    }
    public synchronized void test() {
        if (ticket > 0) {
            System.out.println(Thread.currentThread().getName() + "卖出了第" + ticket +"票");

            ticket--;
        } else {
            System.out.println("票已经买完了");
            return;
        }

    }
}
public class Demo2 {
    public static void main(String[] args) {
        //强调的是:多个线程操作同一个数据  ticket
        SaleTicket1 saleTicket = new SaleTicket1();

        new Thread(saleTicket, "线程1").start();
        new Thread(saleTicket, "线程2").start();
    }
}

1.7Java中的锁

synchronized 被称为隐式锁,会自动释放,是一个非公平的锁

Lock锁 被称为显示锁

他们两个锁都可以解决线程同步的问题。但是synchronized 更加强大,更加粒度化。更加灵活。

一般开发的时候用synchronized

Lock是一个接口,实现ReentrantLock

有两个重要方法:

​ lock();

​ unlock();

class SaleTicket1 implements Runnable {
    private int ticket = 100;
    ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {

        while (true) {
            try{


                lock.lock();
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + "卖出了第" + ticket + "票");

                    ticket--;
                } else {
                    System.out.println("票已经买完了");
                    break;
                }
            } catch (Exception e) {

            } finally {
                lock.unlock();
            }


        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        //强调的是:多个线程操作同一个数据  ticket
        SaleTicket1 saleTicket = new SaleTicket1();

        new Thread(saleTicket, "线程1").start();
        new Thread(saleTicket, "线程2").start();
    }
}

1.8守护线程

守护线程是用来守护非守护线程的

class MyThread8 implements  Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("守护线程:" + i);
        }
    }
}

public class Demo3 {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.isDaemon());//false  非守护线程
       // thread.setDaemon(true);//设置为守护线程
        Thread thread1 = new Thread(new MyThread8());
        //System.out.println(thread1.isDaemon());
        thread1.setDaemon(true);
        thread1.start();
        for (int i = 0; i < 200; i++) {
            System.out.println("主线程:" + i);
        }


    }
}

2.死锁

开发中禁止出现死锁

应用场景: 并发场景,多个线程。线程之间在共享数据的时候 是互不相让的

线程加锁为了线程安全,但是物极必反。

死锁是一种状态,当两个线程互相持有对象所需要的资源的时候,这两个线程又都不主动释放资源

就会导致死锁。代码无法正常执行。这两个线程就会僵持住

class DeadLock implements Runnable {
    private boolean flag;//标记
    private Object obj1;//对象1
    private Object obj2;//对象2

    public DeadLock(boolean flag, Object obj1, Object obj2) {
        this.flag = flag;
        this.obj1 = obj1;
        this.obj2 = obj2;
    }

    @Override
    public void run() {
        if (flag) {//如果flag = true 让线程1执行这个if语句里面的代码
            synchronized (obj1) {
                System.out.println(Thread.currentThread().getName() + "拿到了obj1资源");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1执行了");
                synchronized (obj2) {//想用obj2这个资源
                    System.out.println(Thread.currentThread().getName() + "拿到obj2资源");
                }
            }
        }
        if (!flag) {//如果flag=false 线程2 执行这个if语句里面的代码
            synchronized (obj2) {
                System.out.println(Thread.currentThread().getName() + "拿到了obj2资源");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程2执行了");

                synchronized (obj1) {
                    System.out.println(Thread.currentThread().getName() + "拿到obj1资源");
                }
            }

        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Object obj1 = new Object();
        Object obj2 = new Object();
        DeadLock deadLock1 = new DeadLock(true, obj1, obj2);
        new Thread(deadLock1, "线程1").start();
        DeadLock deadLock2 = new DeadLock(false, obj1, obj2);
        new Thread(deadLock2, "线程1").start();
    }
}

3.Object类下面的和线程有关的方法

public final void wait()
             throws InterruptedException

导致当前线程等待,知道另一个线程调用该对象的notify()方法或notifyAll()方法

总结: 至少两个线程,对象.wait(),那么当前线程就会等待

//为啥写Message这个类?  wait方法    对象.wait(); 创建Message对象
    //
class Message {
    private String message;//信息

    public Message(String message) {
        this.message = message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

}
//线程类  等待线程
class WaitThread implements Runnable {
    private Message message;

    public WaitThread(Message message) {
        this.message = message;
    }
//等待线程抢到了
    //等待线程睡了5秒  然后唤醒线程执行。  synchronized (message)
    //message  对象从等待池中国去取的,结果发现没有  阻塞
    //回到等待线程睡醒了以后开始   wait等待

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + "正在等待中....");

        synchronized (message) {
            try {

                //当调用wait方法的时候,会自动释放锁,并将对象放到等待池中,让唤醒线程锁来操作这个对象
                //
                message.wait();//代码走到这一步 当前线程会等待!!!
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name +"被唤醒!!!Line45行的");
            System.out.println(message.getMessage());
        }
    }
}
//唤醒线程
class NotifyThread implements Runnable {
    private Message message;

    public NotifyThread(Message message ) {
        this.message = message;
    }
    @Override public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("唤醒线程已经执行");
       synchronized (message) {
            message.setMessage("我是修改之后的message对象");
            //message.notify();
            message.notifyAll();

       }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Message message = new Message("我是message对象");
        WaitThread waitThread = new WaitThread(message);
        WaitThread waitThread1 = new WaitThread(message);
        NotifyThread notifyThread = new NotifyThread(message);

        new Thread(waitThread1, "wait2线程").start();
        new Thread(waitThread, "wait1线程").start();
        new Thread(notifyThread, "notify线程").start();

    }
}

4.线程的生命周期

1.线程的创建启动 start()

2.线程可运行状态 抢占 等待cpu

3.线程运行状态 抢占 和执行

4.线程的阻塞 wait sleep 锁

5.线程的消亡 destroy

5.join方法

作用:让父线程等待,一直等到子线程结束以后,父线程才会执行。

join方法实例:

class MyThread1 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName() +":" + i);
        }
    }
}
public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new MyThread1(), "子线程");

        thread.start();
        thread.join();//主线程等待 子线程先执行,
        for (int i = 0; i < 1000; i++) {
            System.out.println("主线程:" + i);
        }
        
    }
}

class FatherThread implements Runnable {
    @Override
    public void run() {
        //在fathe线程去启动儿子线程
        Thread thread = new Thread(new SonThread());

        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 100; i++) {
            System.out.println("父线程:" + i);
        }
    }
}
class SonThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("儿子线程:" + i);
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        new Thread(new FatherThread()).start();
    }
}

6.生产者消费者模式

生产线程负责生产,消费线程负责消费。

生产线程和消费线程要达到均衡。

这是一种特殊的业务需求,在这种特殊的情况下需要使用wait方法和notify方法

//为啥要写这个类 商品类
class Goods {
    private String name;//商品的名字
    private double price;//商品的价格
    private boolean isProduct;//商品是否需要生产
    //true需要生产    false 不需要生产


    public Goods(String name, double price, boolean isProduct) {
        this.name = name;
        this.price = price;
        this.isProduct = isProduct;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public boolean isProduct() {
        return isProduct;
    }

    public void setProduct(boolean product) {
        isProduct = product;
    }
}

class Customer implements Runnable {//消费者线程
    private Goods goods;

    public Customer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        //消费者一直消费  生产者一直生产
        while (true) {
            synchronized (goods) {
                //需要一直消费 判断商品是否有无
                // //true需要生产    false 不需要生产
                if (!goods.isProduct()) {
                    //不需要生产直接购买的
                    System.out.println("消费者购买:" + goods.getName() + ",价格为:"+ goods.getPrice());
                    //购买完以后,商品没了,商品标记为true
                    goods.setProduct(true);
                    //唤醒生产者  让其生产
                    goods.notify();
                } else {
                    //需要生产  消费者线程等待
                    try {
                        goods.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
class Productor implements Runnable {//生产者线程
    private Goods goods;

    public Productor(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        int count = 0;

        while (true) {
            try {
                Thread.sleep(20000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (goods) {
                // true需要生产    false 不需要生产
                if (goods.isProduct()) {//true
                    //造车,如果是奇数的话,造玛莎拉蒂  如果是偶数的话,造劳斯莱斯
                    if (count % 2 == 0) {
                        //偶数
                       goods.setName("劳斯莱斯");
                       goods.setPrice(8.9);

                    } else {
                        //奇数
                        goods.setName("玛莎拉蒂");
                        goods.setPrice(7.6);
                    }
                    //生产者生产者完以后,将isProcut标记为
                    goods.setProduct(false);
                    System.out.println("生产者生产了:" + goods.getName() + ",价格为:" + goods.getPrice());
                    count++;
                    //生产者生产完以后 唤醒消费者。
                    goods.notify();
                } else{
                    //不需要生产的
                    try {
                        goods.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Goods goods = new Goods("红旗", 9.9, false);

        Customer customer = new Customer(goods);
        Productor productor = new Productor(goods);
        new Thread(customer).start();
        new Thread(productor).start();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值