线程

一、进程和线程的区别

进程

1、就是独立的程序,通过系统分配,获取系统的CPU、内存、显卡、网络和磁盘这些资源。
2、由多个线程组成,而且至少有一个线程
3、进程申请的是系统的资源
4、具有独立性和互斥性

线程

1、线程就是进程中的一个功能
2、抢占式运行:CPU执行程序是按照时间片来进行执行的。
3、资源共享:一个当前程序中的线程可以共享程序的资源,如CPU
4、线程申请的是进程的资源

二、线程的优缺点

优点:

1、提高资源的利用率
2、电脑可以同时执行多个程序,提高工作效率
3、提升用户体验

劣势:

1、加重CPU的负担
2、降低CPU执行其他线程的概率,用户体验会卡顿
3、共享资源的问题
4、死锁(避免)

三、创建自定义线程的两种方式

Thread类是线程的基类

方式1:自定义一个线程类,继承extends Thread,重写run方法
方式2:自定义线程类,实现一个接口 Runnable ,并实现run方法
推荐第二种方式
原因:java中继承是单继承,一个类只能继承一个类,如果一个类继承了Thread类就无法继承其他类,当时可以实现多个接口

示例

class MyThread1 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("继承Thread的自定义线程");
        }
    }
}

class MyThread2 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("实现Runnable的自定义线程");
        }
    }
}

public class Demo1 {
    public static void main(String[] args) {
        /**
         * 如何来执行线程中的代码
         *  方法1:
         *       创建自定义线程的类对象
         *       使用start方法开启线程
         *     【错误操作】:
         *          不能直接调用run
         */
        //此线程开始执行; Java虚拟机调用此线程的run方法。
        MyThread1 myThread1 = new MyThread1();
        myThread1.start();

        /**
         * 方法2:
         *      创建自定义线程类的对象
         *      把自定义线程对象当成一个参数放到Thread类中
         *      使用Thread类对象调用start()
         */
        MyThread2 myThread2 = new MyThread2();
        Thread thread = new Thread(myThread2);
        thread.start();

        for (int i = 0; i < 100; i++) {
            System.out.println("这个是main主线程的线程代码");
        }
    }
}

四、线程中常用的方法

Thread类的构造方法:

Thread():创建一个Thread线程的类对象,没有指定目标代码和线程名字

Thread(Runnable target):创建一个Thread类的对象,传入的参数是一个Runnable接口实现的类对象。

Thread(Runnable target,String name):创建一个Thread类的对象,传入的参数是一个Runnable接口实现的类对象并给线程起名字

Thread类的静态方法:

static Thread currentThread():该方法在哪里执行就获取的是哪里的线程对象
static void sleep():让当前线程休眠指定的毫秒数

Thread类的成员方法:

void setName(String name):设置线程的名字
String getName():获取线程的名字
void setPriority(int new Priority):设置线程的优先级,优先级只能增加执行概率,不能确定一定先执行。线程默认的为5, 1~10 最高的是10 最低的1
int getPriority(): 获取当前线程优先级

示例:

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

        Thread t1 = new Thread();

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("吃早饭");
                }
            }
        },"线程2");

        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("吃午饭");
                }
            }
        },"线程3");

        System.out.println(t1);//Thread[Thread-0,5,main]  线程的名字   优先级  在哪个线程组里
        System.out.println(t2);
        System.out.println(t3);
        System.out.println(t3.getName());//线程3
        System.out.println(Thread.currentThread());//Thread[main,5,main]
        t2.setPriority(10);
        System.out.println(t2.getPriority());//10

        t1.start();
        t2.start();
        t3.start();
    }
}

五、同步代码块

用来处理共享资源问题

例如:
1、ATM机,一个人在办理业务的时候,里面要锁门之后其他人要排队。
2、上厕所大号,你要锁上门别人来排队,你结束以后,开锁之后,别人上。

示例

电影院 《你好,李焕英》 100张票
这里有三种订票方式,需要共同卖这100张票,100张票是三个销售渠道的共享资源
每一个销售渠道都是一个线程。
淘票票 猫眼 美团

问题一:
这个100张票该怎么保存???选择什么类型的数据???
int类型的数据

问题二:
创建三个销售线程类的对象,如果ticket是成员变量,每一个销售线程里面都会有自己的成员变量。这样ticket就不是共享资源,相互不干扰的。-----不行
定义在方法中,只能定义在run方法中,运行一个run,ticket会重新定义一次----不行
类变量:静态的成员变量保存在数据区,可以提供给所有当前类使用。而且一处修改,处处修改,是一个 不错的选择

问题三:存在一张票卖出去3次的情况
解决方案:同步代码块
sysnchronized(/锁对象/) {
//加锁的代码
}
1.在这个代码块内,只能出现一个线程执行
2.锁对象可以是任意类型的对象
3.同步代码块包含的代码越少越好
4.Thread.sleep();不会开启锁对象

class SaleTicket implements Runnable {

    private static int ticket = 100;

    @Override
    public void run() {
        synchronized ("锁") {
            while (true) {
                if (ticket > 0) {
                    /*
                     * 为什么这个地方只能捕获???
                     * 因为这个地方实现的是接口中的方法,使用到了注解@Override
                     * 要求开启了重写的严格检查。重写要求方法的声明必须保持一致
                     *异常的抛出属于方法声明的一部分。
                     *而在Runnable接口中,run方法没有抛出异常。
                     *所以只能捕捉
                     */
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "售出了第" + (101 - ticket) + "张票");
                    ticket--;
                } else {
                    System.out.println("卖完了");
                    break;
                }
            }
        }
    }
}

public class Demo3 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new SaleTicket(),"淘票票");
        Thread t2 = new Thread(new SaleTicket(),"美团");
        Thread t3 = new Thread(new SaleTicket(),"猫眼");
        t1.start();
        t2.start();
        t3.start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值