JAVA多线程基础

Posted innndown

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA多线程基础相关的知识,希望对你有一定的参考价值。

1. 多进程与多线程

多进程

  • 每个独立执行的任务就是一个进程

  • 操作系统将时间划分为多个时间片,在每个时间片内将CPU分配给某一个任务,时间片结束,CPU将自动回收,再分配给其他任务

  • 多进程的缺点:比较笨重不好切换

多线程

  • 一个程序可包多个子任务,可串并行

  • 一个子任务可以称为一个线程

  • 在一个线程阻塞时,CPU可以调度另一个线程工作,这样CPU还是保留在本程序中。

2. java实现多线程的两种方法

1.线程继承Thread类,实现run方法。

public class Thread1 extends Thread{
    public void run()
    {
        System.out.println("hello");
    }
    public static void main(String[] a)
    {
        new Thread1().start();
    }
}

2.线程实现Runnable接口,实现run方法。(Runnable对象必须放在一个Thread类中才能运行)

public class Thread2 implements Runnable{
    public void run()
    {
        System.out.println("hello");
    }
    public static void main(String[] a)
    {
        new Thread(new Thread2()).start();
    }
}
  • start()方法会自动调用run方法

  • 直接调用run()方法,会变成串行执行

  • main函数(线程)可能遭遇新线程结束,整个程序并不终止
  • 整个程序终止时等所有的线程都终止

3. 多线程信息共享

应该注意两种实现方法信息共享的区别。

  • 继承Tread类,只能通过设置Static静态常量实现变量共享,静态变量只有一个值。
public class ThreadDemo0
{
    public static void main(String [] args)
    {
        new TestThread0().start();
        new TestThread0().start();
        new TestThread0().start();
        new TestThread0().start();
    }
}
class TestThread0 extends Thread  
{
    //private int tickets=100;           //每个线程卖100张,没有共享
    private static int tickets=100;  //static变量是共享的,所有的线程共享
    public void run()
    {
        while(true)
        {
            if(tickets>0)
            {
                System.out.println(Thread.currentThread().getName() +
                " is selling ticket " + tickets);
                tickets = tickets - 1;
            }
            else
            {
                break;
            }
        }
    }
}
  • 实现Runnable接口,设置一个private常量,TestThread1变量只被创建一次,而new Thread(t).start()只是把t包装为不同的对象,所以使用的是同一个对象,普通成员变量即可共享信息。

public class ThreadDemo1
{
    public static void main(String [] args)
    {
        TestThread1 t=new TestThread1();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
    }
}
class TestThread1 implements Runnable
{
    private int tickets=100;
    public void run()
    {
        while(true)
        {
            if(tickets>0)
            {
                System.out.println(Thread.currentThread().getName() +" is selling ticket " + tickets);
                tickets--;
            }
            else
            {
                break;
            }
                
        }
    }
}

但是上述方法会存在工作副本的问题,应该采用volatile关键字使变量可以再各个进程之间通信,以及使用互斥锁synchronized对关键步骤进行加锁限制

//1.改写runnable接口方法
public class ThreadDemo3 {
    public static void main(String[] args) {
        TestThread3 t = new TestThread3();
        new Thread(t, "Thread-0").start();
        new Thread(t, "Thread-1").start();
        new Thread(t, "Thread-2").start();
        new Thread(t, "Thread-3").start();
    }
}

class TestThread3 implements Runnable {
    private volatile int tickets = 100; // 多个 线程在共享的

    public void run() {
        while (true) {
            sale();
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            if (tickets <= 0) {
                break;
            }
        }

    }

    public synchronized void sale() { // 同步函数
        if (tickets > 0) {
            System.out.println(Thread.currentThread().getName() + " is saling ticket " + tickets--);
        }
    }
}
//2.改写继承Thread类的方法
public class ThreadDemo0
{
    public static void main(String [] args)
    {
        new TestThread0().start();
        new TestThread0().start();
        new TestThread0().start();
        new TestThread0().start();
    }
}
class TestThread0 extends Thread  
{
    volatile private static int tickets=100;  //static变量是共享的,所有的线程共享
    public void run() {
        while (true) {
            sale();
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            if (tickets <= 0) {
                break;
            }
        }

    }

    public static synchronized void sale() { // 同步函数
        if (tickets > 0) {
            System.out.println(Thread.currentThread().getName() + " is saling ticket " + tickets--);
        }
    }
}

总结

1.实现共享变量必须使这个变量的值只有一个。

2.某段时间只有一个进程对这个值操作。

3.应该让其他进程知晓这个变量的变化。

4. 多线程管理

4.1. 生产者消费者模型

package product;

/**
 *仓库
 */
class Storage {
    // 仓库容量为10
    private Product[] products = new Product[10];
    private int top = 0;

    // 生产者往仓库中放入产品
    public synchronized void push(Product product) {
        while (top == products.length) {
            try {
                System.out.println("producer wait");
                wait();//仓库已满,等待
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //把产品放入仓库
        products[top++] = product;
        System.out.println(Thread.currentThread().getName() + " 生产了产品"
                + product);
        System.out.println("producer notifyAll");
        notifyAll();//唤醒等待线程
        

    }

    // 消费者从仓库中取出产品
    public synchronized Product pop() {
        while (top == 0) {
            try {
                System.out.println("consumer wait");
                System.out.println(top);
                wait();//仓库空,等待
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

        //从仓库中取产品
        --top;
        Product p = new Product(products[top].getId(), products[top].getName());
        products[top] = null;
        System.out.println(Thread.currentThread().getName() + " 消费了产品" + p);
        System.out.println("comsumer notifyAll");
        notifyAll();//唤醒等待线程
        return p;
    }
}

notify(),与notifyall()方法用来唤醒等待进程
wait()方法等待

4.2. 线程

java线程的状态

java的monitor监视器

java的monitor监视器

synchronized关键字

5.java线程组:

并行计算的模式:

  • 主从模式
  • worker模式

线程组ThreadGroup:
没有解决高度耦合。

以上是关于JAVA多线程基础的主要内容,如果未能解决你的问题,请参考以下文章

java基础入门-多线程同步浅析-以银行转账为样例

java多线程基础

Java基础之多线程

Java多线程基础

多线程编程学习一(Java多线程的基础)

Java 多线程基础多线程的实现方式