线程

1.线程概述

程序,进程,线程

程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码。(静态的代码)

进程((process)就是正在执行的程序,从Windows角度讲,进程是含有内存和资源并安置线程的地方.(运行中的程序,加载到内存中执行).

线程(thread)进程可进一步细化为线程,是一个进程内部的最小执行单元.

进程与线程的关系

一个进程中可以包含多个线程,一个线程只能属于一个进程,线程不能脱离进程存在.

一个进程中至少包含一个线程,即主线程,java中的main就是主线程

所有线程共享进程资源

在主线程中可以创建并启动其他线程

多线程

多线程:在一个进程内,同时拥有多个线程.执行多个任务

何时需要多线程

​ 程序需要同时执行多个任务(任务/线程 都是各自独立的)

多线程优点

同时执行多个任务,功能强大

提高cpu利用率 cpu执行是以线程为单位

改善程序结构,将复杂任务分为对个线程,独立运行.

多线程缺点

线程月多,对内存,cpu的占用高.(硬件升级)

多个线程对同一个共享的资源进行访问,会出现各种不正常情况

解决办法:线程同步 效率低

2.创建线程

1.继承Thread类

//在主线程中创建并启动其他线程
          ThreadDemo t = new ThreadDemo();//创建线程
                     t.start();//启动线程,线程是独立的,可以由cpu加载执行

2.实现Runnable接口

//创建了一个线程要执行的任务
         ThreadDemo threadDemo = new ThreadDemo();
         //创建线程,并将线程中需要执行的任务添加到线程中
         Thread  t = new Thread(threadDemo);
                 t.start();//启动线程

实现Runnable接口好处

1.避免单继承, 实现接口还可以继承其他类

2.多个线程可以共享同一个接口实现类的对象,非常适合多个相同线程来处理同一份资源。(线程同步)

3.线程中用到方法:

run() 编写线程中需要执行的任务代码

start() 启动线程

Thread类的构造方法

Thread(Runnable target)

Thread(Runnable target,String name) 为线程命名

Thread.currentThread() 获得当前正在执行的线程
getName() 获取到线程名称
setName(“名称”)为线程设置名称

4.线程优先级

java中线程的优先级 用整数表示 1-10

默认情况下线程的有限级为5

setPriority(1)设置线程优先级
getPriority()获得线程优先级

牵扯到cpu的执行权

cpu执行的策略:

时间片: 就是排队,先来先执行

抢占式: 对优先级高的先执行

5.影响线程状态的方法

public static void main(String[] args) {
        ThreadDemo  t1 = new ThreadDemo();//创建线程  新建状态(不能执行)
                    t1.setName("线程1");
                    t1.start(); //启动线程   就绪状态(准备好了,随时等待cpu加载)
                                //当线程获得了cpu的执行权,进入到运行状态
                                //当线程失去cpu执行权(因为cpu还要轮流执行其他的线程),进入到就绪状态
                                //当线程中所有的任务执行完成后,进入死亡状态(销毁)

                   t1.stop(); //强制让线程销毁

            /*try {
                t1.join();//线程合并,等待t1线程执行完毕后 ,其他线程执行,(应用场景,另一个线程中需要使用到第一个线程中数据)
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/

        ThreadDemo  t2 = new ThreadDemo();
                    t2.setName("线程2");
                    t2.start();

                    t2.stop();

    }



 @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
           /*  if(i%5==0){
                Thread.yield();//线程主动让步(让出cpu执行权),
            }*/
            try {
                Thread.sleep(1000);//让线程休眠指定的时间,进入阻塞状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }

6.守护线程

是特殊的一种

当把一个线程设置为守护线程时,守护线程需要等所有的非守护线程全部结束后,才会销毁.

ThreadDemo t = new ThreadDemo();            
t.setDaemon(true);//将线程设置为守护线程,必须在线程启动之前设置            
t.start();

jvm中的垃圾回收 就是一个典型的守护线程

多线程同步

同步的前提:

多线程情况下.

多个线程访问同一个共享数据(资源).

并发与并行
**并行:**多个CPU同时执行多个任务。比如:多个人同时做不同的事。
**并发:**一个CPU(采用时间片)同时执行多个任务。比如:秒杀、多个人做同一件事。

线程同步前提:多线程,多个线程访问同一个共享资源.

同步机制: 排队+锁

static 变量 随着类的加载而加载.生命周期比较长

非static 变量 生命周期与对象相同

线程同步方式

synchronized修饰代码块
synchronized修饰方法

线程死锁

相互持有对方线程中需要的锁,

死锁出现不会报错,不会提示,只是等待.

JDK5之后使用Lock方式显示的加锁,释放锁

Lock是显式锁(手动开启和关闭锁,别忘记关闭锁), 实现类ReentrantLock
synchronized是隐式锁,出了作用域自动释放

Lock只有代码块锁

synchronized 有代码块锁,方法

线程通信

就是多个线程之间相互牵制,相互调度执行

wait() 让线程等待 阻塞 不会自动唤醒

notify() 唤醒等待的线程 如果有多个,那就唤醒优先级高

notifyAll() 唤醒所有等待的线程

wait() notify notifyAll必须在同步代码块中执行

消费者生产者问题

​ 创建柜台资源

package ff.learn.javaThread.w03;

/**
 * 柜台
 */

public class Counter {

    int unm = 0;
    //生产
    public synchronized void add(){
       if(unm==0){
           unm++;
           System.out.println("生产者生产了商品");
           this.notify();//唤醒消费者
       }else {
           try {
               this.wait();//让生产者等待
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
    }
    //消费
    public synchronized void sub(){
        if(unm==1){
            unm--;
            System.out.println("消费者取走商品");
            this.notify();//唤醒生产者
        }else {
            try {
                this.wait();//消费者等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

创建消费者线程

package ff.learn.javaThread.w03;

/**
 * 消费者线程
 */
public class Customer extends Thread{
    Counter c ;

    public Customer(Counter c) {
        this.c = c;
    }

    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            c.sub();
        }
    }
}

创建生产者线程

package ff.learn.javaThread.w03;

/**
 * 生产者
 */
public class Productor extends Thread{
    Counter c ;

    public Productor(Counter c) {
        this.c = c;
    }
    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            c.add();
        }
    }
}

测试程序

package ff.learn.javaThread.w03;

public class Test03 {
    public static void main(String[] args) {
        Counter c = new Counter();//柜台
        Productor p = new Productor(c);//生产者
        Customer cu = new Customer(c);//消费者
        p.start();
        cu.start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值