线程及线程创建

什么是线程?

1.线程由进程创建,是进程的一个实体

2.一个线程可有多个进程

单线程:

同一时刻只有一个

多线程:

同一时刻多个

并发:

一会一会,交替执行

并行:

一边一边,同时执行

创建线程的两种方式:

1.继承Thread类,重写run方法

class Cat extends Thread{
    public void run(){
        int times=0;
        while(true) {
            System.out.println("哈喽哈喽"+(++times)+"线程-            
                     >"+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if(times==20){
                break;
            }
        }
    }
}
/*-----------------------------------------------------------*/
public class ThreadEgTest {
    public static void main(String[] args) throws InterruptedException {
        Cat cat = new Cat();
        cat.start();//启动线程,最终会执行cat的run方法
        //调start,底层是start0(),是本地方法,JVM调用,底层是c/c++实现,
        //真正实现多线程的效果,是start0(),而不是run
        //用的是start而不是直接用run方法,因为run方法就是一个普通的方法,
        //没有真正的启动线程,它会把run方法执行结束后才向下执行
        System.out.println("主线程继续执行"+Thread.currentThread().getName());
        //主线程结束,如果还有其他子线程在跑,那么应用程序不会结束,还有子线程要继续执行完
        for(int i=0;i<10;i++){
            System.out.println("主线程 i="+i);
            Thread.sleep(1000);
        }
    }
}

2.实现Runnable接口,重写run方法

class Dog implements Runnable{//通过实现Runnable接口,开启线程
    int count=0;
    public void run(){
        while(true){
            System.out.println("小狗汪汪叫"+(++count)+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if(count==10){
                break;
            }
        }
    }
}
/*--------------------------------------------------------------------------------------*/
public class DogTest {
    public static void main(String[] args) {
        Dog dog=new Dog();
        //dog.start(); 这里不能调用start;
        //创建Thread对象,把dog对象(实现Runnable)接口,
        Thread thread=new Thread(dog);
        thread.start();
    }
}

3.实现Callable接口:

实现call()方法,用FutureTask()封装实现类。使用FutureTask对象作为Thread对象调用start()启动线程,调用FutureTask对象的get()方法获取返回值()。

Thread和Runnable的区别:

1.本质上二者没有区别,因为底层都是靠start()来实现(底层调用start0()),Thread类本身就实现了Runnable接口.

2.用法上有所区别,实现Runnable接口方式更适合多个线程共享一个资源的情况,并且避免了单继承的限制

Runnable和Callable的区别: 

(1)Callable规定的方法是call(),Runnable规定的方法是run()。
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值得。
(3)call方法可以抛出异常,run方法不可以,因为run方法本身没有抛出异常,所以自定义的线程类在重写run的时候也无法抛出异常
(4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

 线程常用方法:

第一组:

1.setName 设置线程名称,使之与参数name相同

2.getName 返回该线程的名称

3.start         使线程开始执行 ; Java虚拟机底层调用该线程的start0方法

4.run           调用线程对象run方法

5.setPriority 更改线程的优先级

6.getPriority 获取线程的优先级

7.sleep         在指定毫秒数内让当前正在执行的线程休眠

8.interrupt    中断线程(不是终止)

第二组:

1.yield:

线程的礼让。让出cpu,让其他线程执行,但礼让的时间不确定,所以也不一定礼让成功

2.join:

线程的插队。插队的线程一旦插队成功,则肯定先执行完插入的线程所有的任内。

守护线程:

当所有的用户线程结束,守护线程自动结束

常见的守护线程:垃圾回收机制

线程的七大状态:

Runnable 可细分为Ready和Running

可运行状态  可细分为就绪状态和运行状态

互斥锁:

1.Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性

2.每个对象都对应一个可称为互斥锁的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象

3.关键字synchronized来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问

4.同步的局限性:导致程序的执行效率要降低

5.同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)

6.同步方法(静态的)的锁为当前类本身

注意事项和细节:

1.同步方法如果没有使用static修饰,默认锁对象为this

2.如果方法使用static修饰,默认锁对象:当前类.class

3.实现步骤:先分析上锁的代码,选择同步代码块或方法(同步代码块更好,范围更小,效率更高),要求多个线程的锁对象为同一个(才能锁住,如果每个对象各有一把锁,就等同于各自执行导致锁无效,相当于一个厕所有三个门但只有一个坑位,三个人进去在同一个坑位上厕所)。

public class SellSynchronized {
    public static void main(String[] args) {
        SellTicket windows=new SellTicket();
        new Thread(windows).start();
        new Thread(windows).start();
        new Thread(windows).start();
    }
}
class SellTicket implements Runnable{
    private static int ticketsNum=1000;
    private boolean loop=true;
    Object object=new Object();
    //同步方法(静态的)的锁为当前类本身
    public synchronized static void m1(){

    }
    //如果在静态方法中,实现一个同步代码块,在类本身,用类.class
    public static void m2(){
        synchronized (SellTicket.class) {
            System.out.println("m2");
        }
    }
    public /*synchronized*/ void sell() { //这个锁在this对象,同步方法锁,是在方法上加锁
        //也可以在代码块上加,就是同步代码块
        synchronized (/*this*/object/*new Object()*/) {
            if (ticketsNum <= 0) {
                System.out.println("没票啦!");
                loop = false;
                return;
            }
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票"
                    + "剩余票数为" + (--ticketsNum));
        }
    }
    public void run(){
        while(loop){
            sell();
        }
    }
}

 死锁:

案例:

妈妈:你先完成作业才让你玩手机

小明:你先让我玩一会我就完成作业

public class DieLock {
    public static void main(String[] args) {
        DieLockDemo A=new DieLockDemo(true);
        DieLockDemo B=new DieLockDemo(false);
        A.setName("A线程");
        B.setName("B线程");
        A.start();
        B.start();
    }
}
class DieLockDemo extends Thread{
    static Object o1=new Object();
    static Object o2=new Object();
    boolean flag;
    public DieLockDemo(boolean flag){
        this.flag=flag;
    }
    public void run(){
        //业务逻辑分析
        //1.如果flag为true,线程A就会先得到o1对象锁,然后尝试去获取o2锁
        //2.如果线程A得不到o2锁,就会Blocked
        //3.如果flag为false,线程B就会先得到o2对象锁,然后尝试去获取o1锁
        //4.如果线程B得不到o1锁,就会Blocked
        if(flag){
            synchronized (o1){
                System.out.println(Thread.currentThread().getName()+"进入1");
                synchronized (o2){
                    System.out.println(Thread.currentThread().getName()+"进入2");
                }
            }
        }else{
            synchronized (o2){
                System.out.println(Thread.currentThread().getName()+"进入3");
                synchronized (o1){
                    System.out.println(Thread.currentThread().getName()+"进入4");
                }
            }
        }
    }
}

释放锁:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值