进程和线程

进程和线程

       进程和线程是什么?二者的区别是什么?
       实现线程的方法?
       线程中常用的方法?
       线程中有哪些状态?
       线程调度问题?
       线程安全问题?
       Object类中的wait和notify方法?
       生产者和消费者模式

进程和线程及区别

 进程是一个应用程序或软件
 线程是进程的一个执行单元。
 一个进程可以有多个线程。一个线程对应一个栈,栈与栈之间相
 互独立。

实现线程的方法

 1.编写一个类,直接继承java.lang.Thread,重写run方法。

public class ThreadTest01 {
    public static void main(String[] args) {
        //这里的方法是main方法,属于主线程,在主栈中运行
        MyThread myThread = new MyThread();
        //启动线程
        //start方法的作用是启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码任务完成之后,瞬间就结束
        //这段代码是为了开辟一个新的占空间,只要新的栈空间开辟出来,start方法就结束啦,线程就启动成功了。
        //run方法是在分支的栈底部,main方法在主栈的底部。run和main是平级的。
        //注意:直接调用run方法不会启动线程,不会分配新的分支栈。
        myThread.start();
        //这里的代码还是在主栈中运行
        for(int i = 0;i<1000;i++){
            System.out.println("主线程---"+i);
        }
    }
}
class MyThread extends Thread{
    public void run(){
        //编写程序,这段程序运行在分支栈中
        for(int i = 0; i < 1000; i++){
            System.out.println("分支线程---"+i);
        }
    }
}

 代码分析:创建线程对象然后调用线程对象的start方法才能开启
 线程
 start方法的作用:启动一个分支线程,在JVM中开辟一个新的栈
 空间,这段代码任务完成之后,瞬间就结束。
 注意:直接调用run方法不会启动线程,不会分配新的分支栈。
 2.编写一个类,实现java.lang.Runnable接口,实现run方法。

public class ThreadTest02 {
    public static void main(String[] args) {
        //创建一个可运行的对象
        MyRunnable myRunnable = new MyRunnable();
        //将可运行的对象封装成一个线程对象
        Thread thread = new Thread(myRunnable);
        thread.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("主线程"+i);
        }
    }
}
//这不是一个线程类,是一个可运行的接口
class MyRunnable implements Runnable{

    @Override
    public void run() {
        for(int i = 0;i<1000;i++) {
            System.out.println("分支线程" + i);
        }
    }
}

线程中常用的方法

 1.currentThread()方法:用于获取当前线程对象,是一个静态方法

Thread currentthread = Thread.currentThread();
        System.out.println(currentthread);

 2.getName()方法:用于获取线程的名字
  setName()方法:用于修改线程的名字

//MyThread7是一个线程类
        MyThread7 myThread2 = new MyThread7();
        myThread2.setName("tttt");

        System.out.println( myThread2.getName());
        myThread2.start();

 注意:当线程没有设置名字时,默认的名字是Thread-0,Thread-
 1等等
 3.sleep()方法:是静态方法,参数是毫秒。作用是让当前线程进
 入休眠,进入阻塞状态,放弃占有的CPU时间片,让给其他线程使
 用

public static void main(String[] args) {
        //让主线程进入休眠,睡眠5秒
        try {
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //5秒中后输出
        System.out.println("hello world!");
    }

线程中的5中状态

 状态分为5中:新建状态,就绪状态,运行状态,阻塞状态,死亡
 状态
 新建状态:刚new出来的线程对象为新建对象
 就绪状态:调用start方法后线程处于就绪状态。就绪状态又称为
 可运行状态,表示当前线程具有抢夺CPU时间片的权利。当一个线
 程抢夺到CPU时间片后,就开始执行run方法。
 运行状态:调用run方法后线程处于运行状态。当之前占用的CPU
 时间片用完之后,会重新回到就绪状态继续抢夺时间片,当再次
 抢到CPU时间片后会重新进入run方法接着上次的代码继续执行。
 注意:线程之间的运行是多个线程之间交替进行的。
 死亡状态:当run执行结束后线程进入死亡状态。
 阻塞状态:遇到阻塞事件后,就进入阻塞状态。比如sleep方法
 或者接收用户键盘输入。阻塞状态的线程会放弃之前占用的CPU时
 间片。需要再次回到就绪状态才能抢夺CPU时间片。

线程调度问题介绍

 线程调度模型:
    1.抢占式调度模型:哪个线程的优先级比较高,抢到CPU时
    间片的概率就高一些。java采用的就是抢占式调度模型。
    2.均分式调度模型:平均分配CPU时间片,每个线程占有的
    CPU时间片的时间长度一样。
 线程调度相关的方法:
    setPriority(int newPriority):设置线程的优先级
    getPriority( ):获取线程的优先级
    补充:最低优先级是1,默认优先级是5,最高优先级是10;
    优先级高的可能会获得更多的CPU时间片。

    static void yield():暂停当前正执行的线程对象,并执
    行其他线程。执行该方法后不会进入阻塞状态。而是使得
    当前线程从运行状态回到就绪状态。

    void join():合并线程,受阻后进入另一个线程,直到线
    程结束才进行原先的进程
    注意:sleep方法和join方法会进入阻塞状态。

线程安全问题介绍

 在开发过程中,我们的项目都是运行在服务器当中的,而服务器
 已经将线程的定义,线程的创建,线程的启动等都已经实现了,
 这些代码我们都不需要编写。最重要的是编写的程序需要放到一
 个多线程的环境下运行,因此需要关注的是这些数据在多线程并
 发的环境下是否是安全的。

 什么时候会存在安全问题?
    1.多线程并发 2.有共享数据 3.共享的数据有修改行为。
    比如我们日常的ATM取款。
 线程编程模式:
    1.异步编程模型:线程1和 线程2各自执行各自的,谁也不
     需要等谁,这种模型称为异步编程模型
    2.同步编程模型:线程1和线程2,在线程1执行的时候,必
     须等待线程2线程执行结束,或者说,线程2执行的时
     候,必须等待线程1执行结束。两个线程之间发生了等待
     关系。效率较低,但是数据安全。

 线程安全问题解决思路:线程排队执行,不能并发,称为线程同
 步执行。在此过程中会牺牲一定的效率。

 线程同步机制的语法:synchronized(共享对象){ 线程同步代码
 块 },小括号内的数据是相当关键的,这个必须是多线程共享的数
 据( )内写什么要看我们想让哪些线程同步。也就是共享对象。

 Synchronized有两种写法:
    1.在实例方法上使用Synchronized,此时共享对象一定是
     this。并且同步代码块是整个方法体.一个对象一个锁。
    2.在静态方法上使用Synchronized,表示找类锁,类锁永
     远只有一把。
 补充:synchronized会让程序的执行效率降低,用户体验不好,
 系统用户吞吐量(并发量)降低,用户体验差。

 因此我们尽量做到以下几点:
     1.尽量使用局部变量代替实例变量和静态变量
     2.如果必须是实例变量,那么可以考虑创建多个对象,
     这样实例变量的内存就不共享了。
     3.如果不能使用局部变量,对象也不能创建多个,这个
     时候只能选择synchronized了,线程同步机制。

Object类中的wait和notify方法

 第一:wait方法和notify方法不是线程的对象,是java中任何一
     个java对象都有的方法,因为这两个方式是Object类中
     自带的。wait方法和notify方法不是通过线程对象调用
     的。

 第二:wait方法的作用:Object obj = new Object( );
     o.wait( );表示让正在o对象上活动的线程进入等待状
    态,无限期的等待,直到被唤醒。
 第三:notify方法是唤醒等待的线程。

生产者和消费者模式

public class ThreadTest06 {
    public static void main(String[] args) {
   //创建一个仓库对象,共享的
    List list = new ArrayList();

    //创建两个线程对象
        Thread t1 = new Thread(new Product(list));
        Thread t2 = new Thread(new Consumer(list));

        t1.setName("生成线程");
        t2.setName("消费线程");

        t1.start();
        t2.start();
    }
}
//生成线程
class Product implements  Runnable{
    private List list;
    public Product(List list){
        this.list = list;
    }
    @Override
    public void run() {
    //一直生成(使用死循环模拟一直生产)
        while(true){
            synchronized (list){
                if(list.size()> 0){
                    //当前线程进入等待状态
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //程序执行到这,说明list集合是空的,可以生成
                Object obj = new Object();
                list.add(obj);
                System.out.println(Thread.currentThread().getName()+"----->"+obj);
                //唤醒消费线程进行消费
                list.notify();
            }

        }

    }
}
//消费线程
class Consumer implements Runnable{
    private List list;
    public Consumer(List list){
        this.list = list;
    }
    @Override
    public void run() {
    //一直消费
        while (true){
            synchronized (list){
                if(list.size() == 0){
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //程序执行到这里,说明list集合内有元素,可以进行消费
                Object obj = list.remove(0);
                System.out.println(Thread.currentThread().getName()+"--->"+obj);
                list.notify();
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值