多线程的概述和构造方法

一、多线程

	进程的概述和多进程的意义
	线程的概述和多线程的意义
	JVM运行原理以及JVM启动的线程探讨
	实现多线程
	线程调度
	线程控制

二、进程概述及多进程的意义

A:线程和进程
要想说线程,首先必须得聊聊进程,因为线程是依赖于进程存在的。
B:进程概述
什么是进程呢?通过任务管理器我们就可以看到进程的存在。
概念:进程就是正在运行的程序,是系统进行资源分配和调用的独立单位。
每一个进程都有它自己的内存空间和系统资源。
C:多进程的意义
单进程计算机只能做一件事情。而我们现在的计算机都可以一边玩游戏(游戏进程),一边听音乐(音乐进程),
所以我们常见的操作系统都是多进程操作系统。比如:Windows,Mac和Linux等,能在同一个时间段内执行多个任务。
对于单核计算机来讲,游戏进程和音乐进程是同时运行的吗?不是。
因为CPU在某个时间点上只能做一件事情,计算机是在游戏进程和音乐进程间做着频繁切换,且切换速度很快,
所以,我们感觉游戏和音乐在同时进行,其实并不是同时执行的。多进程的作用不是提高执行速度,而是提高CPU的使用率。

线程概述及多线程的意义及并行和并发的区别
并发(concurrency)和并行(parallellism)是:

  1. 解释一:并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
  2. 解释二:并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
  3. 解释三:并行是在一台处理器上“同时”处理多个任务,并发是在多台处理器上同时处理多个任务。如 hadoop 分布式集群。

所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

三、多线程程序实现的方式1

public class MyThread extends Thread{

    @Override
    public void run() {
        //这个run方法就是需要线程来执行的代码,一般耗时的操作,我们就会写在run方法里面,让线程去执行
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}
-------------------------------------------------------------
public class MyTest3 {
    public static void main(String[] args) {
   MyThread th = new MyThread();
        //开启线程,不是调用run方法,调用run()方法,就是你使用一个对象,调用一个方法,让这个方法执行而已,线程并没有开启
        //th.run();
        //正确开启线程的方式是,调用start() 开启线程,由线程去调用run()去执行run方法里面的代码
        th.start();
        //th.start(); 同一个线程不要多次开启,会抛异常
        MyThread th2 = new MyThread();
        th2.start();
    }
}

获取和设置线程对象名称

如何获取main方法所在的线程名称呢?
public static Thread currentThread()//获取当前执行的线程
/**
* 我们现在是想获取主线程的名称,那么我们可不可以先获取到主线程,
如果我们能获取到主线程,那么我们就可以调用getName方法获取对应的名称.
* 如何获取主线程呢? public static Thread currentThread()返回对当前正在执行的线程对象的引用。
* -----------------------------------------------------------------
:Thread类的基本获取和设置方法
public final String getName()//获取线程名称
public final void setName(String name)//设置线程名称
其实通过构造方法也可以给线程起名字

线程调度及获取和设置线程优先级

线程的执行
假如我们的计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,
线程只有得到 CPU时间片,也就是使用权,才可以执行指令。那么Java是如何对线程进行调用的呢?
线程有两种调度模型:
分时调度模型 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
抢占式调度模型 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,
优先级高的线程获取的 CPU 时间片相对多一些。
如何设置和获取线程优先级
public final int getPriority() //获取线程的优先级
public final void setPriority(int newPriority)//设置线程的优先级
线程控制之休眠线程
sleep(long millis) 线程休眠

sleep(long millis) 线程休眠

加入线程: public final void join()
意思就是: 等待该线程执行完毕了以后,其他线程才能再次执行
注意事项: 在线程启动之后,在调用方法

四、 多线程程序实现的方式2

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        //需要线程执行
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}


-----------------------------------------------------------
	public class MyTest {
    public static void main(String[] args) {
      MyRunnable myRunnable = new MyRunnable();
        Thread th = new Thread(myRunnable);
        th.start();

        new MyThread().start();
    }
}
---------------------------------------------

五、 多线程程序实现的方式3

A:实现 Callable 接口。 相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。
B:执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。 FutureTask 是 Future 接口的实现类

实现步骤
1.创建一个类实现Callable 接口
2.创建一个FutureTask类将Callable接口的子类对象作为参数传进去
3.创建Thread类,将FutureTask对象作为参数传进去
4.开启线程

public class MyCallable implements Callable<Integer> {
    //call方法就是线程要执行的方法
    @Override
    public Integer call() throws Exception {
        System.out.println("线程执行了");
        int sum=0;
        for (int i = 1; i <= 100; i++) {
            sum+=i;
        }
        return sum;
    }
}
------------------------------------------------
public class MyTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建线程的方式3
        MyCallable myCallable = new MyCallable();
        FutureTask<Integer> task = new FutureTask<>(myCallable);
        Thread thread = new Thread(task);
        thread.start();
        //线程执行完之后,可以获取结果
        Integer integer = task.get();
        System.out.println(integer);
    }
}

八、 实现Runnable接口的方式卖电影票

案例演示:

public class MyRunnable implements Runnable{

    static int piao = 100;
    @Override
    public void run() {

        while (true) {
            if (piao > 1) {
                String name = Thread.currentThread().getName();
                System.out.println(name + "正在出售" + (piao--) + "张票");
            }
        }
    }
}
---------------------------------------------------------------------
public class MyTest {
    public static void main(String[] args) {
        //A:
        //案例演示
        //需求:某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,
        //请设计一个程序模拟该电影院售票。
        MyRunnable myRunnable1 = new MyRunnable();
        Thread th1 = new Thread(myRunnable1);
        Thread th2 = new Thread(myRunnable1);
        Thread th3 = new Thread(myRunnable1);
        th1.setName("窗口1");
        th2.setName("窗口2");
        th3.setName("窗口3");
        th1.start();
        th2.start();
        th3.start();
    }
}


八、 同步代码块的方式解决线程安全问题

public class MyRunnable implements Runnable {
    static int piao = 100;
    static Object obj = new Object();
    int i=1;
    @Override
    public void run() {

            while (true) {
                //我们在实际网上购票时,会有一些网络延迟,我们可以使用休眠来模拟一下
                //剩余最后两张票
                //th1 th2 th3
                if(i%2==0){
                    //同步代码使用任意对象,作为锁
                    synchronized (MyRunnable.class) { //锁 ,其实就是一个任意对象,多个线程要共享一把锁
                        if (piao >= 1) {
                            try {
                                Thread.sleep(10);//模拟网络延迟 th1
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName() + "正在出售" + (piao--) + "张票");
                        }
                    }
                }else{
                    cellPiao2();
                }
                i++;
                //释放锁
            }
    }
    ---------------------------------
    public class MyTest {
    public static void main(String[] args) {
            MyRunnable myRunnable1 = new MyRunnable();
        Thread th1 = new Thread(myRunnable1);
        Thread th2 = new Thread(myRunnable1);
        Thread th3 = new Thread(myRunnable1);
        th1.setName("窗口1");
        th2.setName("窗口2");
        th3.setName("窗口3");
        th1.start();
        th2.start();
        th3.start();
        }
   }

九、 死锁问题概述和使用

概述
如果出现了同步嵌套,就容易产生死锁问题
是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象
同步代码块的嵌套案例
死锁: 两个或者两个以上的线程,在抢占CPU的执行权的时候,都处于等待状态
举例: 中国人和美国人一起吃饭
中国人使用的筷子
美国人使用的刀和叉
中国人获取到了美国人的刀
美国人获取到了中国人的一根筷子

案例演示:
注意事项: //同步代码块,用的锁对象,是任意锁对象
//同步方法用的锁对象是this
//静态同步方法用的锁对象是 字节码类型

public class MyRunnable implements Runnable {
    static int piao = 100;
    static Object obj = new Object();
    int i=1;
    @Override
    public void run() {
            while (true) {
                 //cellPiao();
                cellPiao2();
            }
    }
    //方法上加有一个synchronized关键字我们叫做同步方法
    //同步方法使用的所对象不是任意对象,他用的锁是this
    private synchronized void cellPiao() {
            if (piao >= 1) {
                try {
                    Thread.sleep(20);//模拟网络延迟 th1
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在出售" + (piao--) + "张票");
            }
    }
    //静态同步方法使用的锁对象,不是任意对象,他用的锁是,当前类的 字节码类型
    private synchronized static void cellPiao2() {
        if (piao >= 1) {
            try {
                Thread.sleep(20);//模拟网络延迟 th1
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在出售" + (piao--) + "张票");
        }
    }
}
------------------------------------------------
public class MyTest {
    public static void main(String[] args) {
        MyRunnable myRunnable1 = new MyRunnable();
        Thread th1 = new Thread(myRunnable1);
        Thread th2 = new Thread(myRunnable1);
        Thread th3 = new Thread(myRunnable1);
        th1.setName("窗口1");
        th2.setName("窗口2");
        th3.setName("窗口3");
        th1.start();
        th2.start();
        th3.start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值