栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java多线程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java多线程

一、线程和进程的区别

进程:

正在运行的程序,是系统进行资源分配和调用的独立单位。

每一个进程都有它自己的内存空间和系统资源。

线程:

是存在于进程中的,一个进程可以包含多个线程的。

单个线程是进程中的单个顺序控制流,或者说就是一个单独执行路径

一个进程如果只有一条执行路径,称之为单线程程序

一个进程如果包含多条执行路径,称之为多线程程序。

二、串行、并行、并发

1、串行,指的是所有的任务都是按照先后顺序执行的,在前一个任务没处理完的情况下

是不会处理下一个任务的,就像理发店只有一个理发师,每个人剪头发的时候都需要

等待前面的人剪完。

2、并行,指的是将任务分给不同的处理器去处理,每一个处理器中的处理是串行,

比如火车站售票会有多个窗口。

3、并发,实质上是一种现象,并发需要处理器的支持,比如在处理一个任务的时候,操作系统

可以进行调度其他的任务,不论串行还是并行,都需要操作系统的支持并发。

假设喝水是一个任务,每个火车售票员在卖票的同时也能喝水,就说明支持并发。(单个cpu通过时间片执行任务)

思考题:

JVM启动的时候是单线程还是多线程的呢?

多线程。 主线程 ,垃圾回收线程 ,JVM在启动的时候,最低要求要有两个线程,JVM启动的时候是多线程。

三、thread的常用方法

//获取当前线程的名字

Thread.currentThread().getName()

1.start():1.启动当前线程 2.调用线程中的run方法

2.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中

3.currentThread():静态方法,返回执行当前代码的线程

4.getName():获取当前线程的名字

5.setName():设置当前线程的名字,还可以通过构造方法设置:new Thread("名字")

6.yield():主动释放当前线程的执行权

7.join():在线程中插入执行另一个线程,该线程被阻塞,直到插入执行的线程完全执行完毕以后,该线程才继续执行下去

8.stop():过时方法。当执行此方法时,强制结束当前线程。

9.sleep(long millitime):线程休眠一段时间

10.isAlive():判断当前线程是否存活

11.守护线程和非守护线程

后台线程 public final void setDaemon(boolean on) (守护线程)

java中有两类线程:用户线程,守护线程

用户线程:我们再学习多线程之前的所有代码,运行起来的时候都是一个个的用户线程

守护线程:所谓的守护线程,指的就是程序运行的时候再后台提供一个通用的服务线程 ,比如说垃圾回收线程,它就是一个称职的守护线程,并且这个线程是程序不可或缺一部分 或者说只要程序存在非守护线程,程序就不会停止 如果一个程序都是守护程序,程序就停止了。(如果非守护线程结束,守护线程也需要停止)

四、线程的调度

调度策略:

时间片:线程的调度采用时间片轮转的方式

抢占式:高优先级的线程抢占CPUJava的调度方法:1.对于同优先级的线程组成先进先出队列(先到先服务),使用时间片策略2.对高优先级,使用优先调度的抢占式策略

等级:MAX_PRIORITY:10 MIN_PRIORITY:1 NORM_PRIORITY:5

方法:getPriority():返回线程优先级

setPriority(int newPriority):改变线程的优先级

注意!:高优先级的线程要抢占低优先级的线程的cpu的执行权。但是仅是从概率上来说的,高优先级的线程更有可能被执行。并不意味着只有高优先级的线程执行完以后,低优先级的线程才执行。

五、线程实现的方式

方式一、继承Thread类,重写run方法

public class Thread1 extends Thread{
    private int tickets = 100;
    @Override
    public void run() {
        if(tickets>0){
            while (true){
                if(tickets>0) {
                    System.out.println(getName() + "正在出售第" + tickets-- + "张票");
                }
            }
        }
    }
}

public class ThreadDemo {
    public static void main(String[] args) {
        Thread1 win1 = new Thread1();
        win1.start();
    }
}

方式二、实现runable接口,实现run方法

public class Thread1 implements Runnable {
    private int tickets = 100;
    @Override
    public void run() {
        while(true){
            synchronized (this) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (tickets > 0) {
                    System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets-- + "张票");
                } else {
                    break;
                }
            }
        }
    }
}


public class ThreadDemo1 {
    public static void main(String[] args) {
        Thread1 thread1 = new Thread1();

        Thread win1 = new Thread(thread1,"窗口一");
        Thread win2 = new Thread(thread1,"窗口二");
        Thread win3 = new Thread(thread1,"窗口三");

        win1.start();
        win2.start();
        win3.start();

    }
}

方式三、 自定义类实现Callable,实现call()方法

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

public class ThreadPoolDemo {
    public static void main(String[] args) {
        //创建线程池对象
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        //创建实现类对象
        ThreadPool threadPool = new ThreadPool();

        //提交任务
        executorService.submit(threadPool);
        executorService.submit(threadPool);

        executorService.shutdown();

    }
}

public class ThreadPool implements Callable {
    private int tickets = 100;
    @Override
    public Object call() {
        while(true){
            synchronized (this) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (tickets > 0) {
                    System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets-- + "张票");
                } else {
                    break;
                }
            }
        }
        return null;
    }
}
六、实现线程安全的方式 1、synchronized关键字

(1)同步代码块的锁对象是谁呢?(修饰代码块)

任意对象,但是多个线程之间锁对象要一样

(2)同步方法?(修饰方法)

将synchronized关键字放到方法上

同步方法的锁对象是this

(3)静态方法的锁对象是谁呢?(修饰静态方法)

class文件,字节码文件对象也是属于一个Object类下面的对象

这个class文件不能是随便一个类的字节码文件

应该是run方法所在类的字节码文件

使用wait和notify方法必须建立在synchronized关键字上(也就是说必须要有锁,wait会释放锁)

2、lock锁

在此之前我们解决线程同步安全问题的时候,使用的是synchronized关键字,通过分析

然后将哪些代码块给包起来,但是,我们并没有直接看到在哪里上了锁,或者说

在哪里释放了锁让其他线程获取到

为了更加清晰的表达如何加锁以及如何释放锁,JDK1.5之后提供了一个新的锁对象

Lock。

Lock(接口)

具体的子类:Class ReentrantLock

void lock() 加锁

void unlock() 释放锁

例子一

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockThreadDemo {
    public static void main(String[] args) {
        //创建一个锁对象
        Lock lock = new ReentrantLock();

        //创建线程实现类
        LockThread lockThread1 = new LockThread(lock);

        //创建线程
        Thread win1 = new Thread(lockThread1, "窗口一");
        Thread win2 = new Thread(lockThread1, "窗口二");
        Thread win3 = new Thread(lockThread1, "窗口三");

        win1.start();
        win2.start();
        win3.start();

}
}

import java.util.concurrent.locks.Lock;

public class LockThread implements Runnable {
    private int tickets = 1000;
    private Lock lock;
    LockThread(Lock lock){
        this.lock = lock;

    }
    @Override
    public void run() {
        while(true){
            lock.lock();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (tickets > 0) {
                    System.out.println(Thread.currentThread().getName()+ "正在出售第" + tickets-- + "张票");
                } else {
                    break;
                }
            lock.unlock();
        }
    }
}

例子二

生产者消费者问题

public class GetBrand implements Runnable {
    private Brand brand;


    public GetBrand(Brand brand) {
        this.brand = brand;
    }

    @Override
    public void run() {
        synchronized (brand){
            while (true) {
                if (brand.getNum() == 0) {
                    try {
                        brand.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                brand.setNum(brand.getNum() - 1);
                System.out.println("有顾客买走了一个包子,现在有" + brand.getNum() + "个包子");

                brand.notify();
            }
        }
    }
}


public class SetBrand implements Runnable{
    private Brand brand;


    public SetBrand(Brand brand) {
        this.brand = brand;
    }

    @Override
    public void run() {
        synchronized (brand) {
            while (true) {
                if (brand.getNum()>=20) {
                    try {
                        brand.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                brand.setNum(brand.getNum() + 1);
                System.out.println("刚刚制作了一个包子,现在有" + brand.getNum() + "个包子");
                brand.notify();

            }
        }
    }
}



public class Brand {
    private int num = 0;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}



public class Test {
    public static void main(String[] args) {

        Brand brand = new Brand();

        GetBrand getBrand = new GetBrand(brand);
        SetBrand setBrand = new SetBrand(brand);

        Thread thread = new Thread(getBrand);
        Thread thread1 = new Thread(setBrand);

        thread.start();
        thread1.start();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/686388.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号