基础4-高级-多线程

概念 实现方式 线程方法 线程同步 线程安全 线程死锁 线程通讯 线程互斥锁

概念

多线程:如果把QQ比作进程,那么既聊天,又玩农场,就是多线程
并发:甲任务与乙任务切换进行
并行:甲任务与乙任务同时进行
举例:jvm是多线程,Jvm启动了垃圾回收线程和主线程

实现方式:三种

第一种---Thread类

public class  HelloWorld {
    public static void main(String[] args) {
        //3、启动start
       new thread().start();
        for (int i=0;i<100000;i++){
            System.out.println("主线程");
        }
    }
}
//1、继承Thread
class thread extends Thread{
    //2、实现run方法
   public void run(){
       for (int i=0;i<100000;i++){
           System.out.println("副线程");
       }
   }
}



第二种---Runnable接口

public class  HelloWorld {
    public static void main(String[] args) {
        //3、调用Thread类
        Thread th = new Thread(new thread());
        //4、启动start方法
        th.start();
        for (int i=0;i<100000;i++){
            System.out.println("主线程");
        }
    }
}
//1、实现Runnable
class thread implements Runnable{
    //2、实现run方法
   public void run(){
       for (int i=0;i<100000;i++){
           System.out.println("副线程");
       }
   }
}


第三种---匿名方式

public class  HelloWorld {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<100000;i++){
                    System.out.println("第一线程");
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<100000;i++){
                    System.out.println("第二线程");
                }
            }
        }).start();
    }
}

线程方法

1、优先级 setPriority()
2、睡眠时间 sleep()
3、线程插队 join()
4、礼让线程 yield()
5、后台运行 setDaemon(true)


public class  HelloWorld {
    public static void main(String[] args) {
        Thread th=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<100000;i++){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("第一线程");
                }
            }
        });

        Thread th2=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<100000;i++){
                    if (i == 9999){
                        try {
                            th.join();//线程插队
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (i == 54654){
                        Thread.yield();//让出CPU
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("第二线程");
                }
            }
        });
        th.setPriority(8);//从1-10 逐次增加
        th.setDaemon(true);//设置守护线程(后台运行,占资源少)
        th.start();
        th2.start();
    }
}

线程同步

package exercise;
/*
当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中
CPU不要切换到其他线程工作,这时就需要同步。如果两段代码是同步的,
那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段
代码。所谓同步代码块就是使用synchronized关键字加上一个锁对象来定义
一段代码,这就叫同步代码块,多个同步代码块如果使用相同的锁对象,那
么他们就是同步的。
 * */
class exercise{
    //开始跑类方法
    public static void main(String[] args) {
        Print print=new Print();
        new Thread(){
            public void run(){
                while(true){
                    print.print();
                }
            }
        }.start();
        
        new Thread(){
            public void run(){
                while(true){
                    print.print1();
                }
            }
        }.start();
    }
}
//创建对象,创建方法
class Print {
    Demo demo=new Demo();
    public void print(){
        synchronized (demo) {
            System.out.println("黑马");
            System.out.println("程序");
        }
    }
    public void print1(){
        synchronized(demo){
            System.out.println("传智");
            System.out.println("博客");
        }
    }
}
//要跑的类
class Demo{}

线程安全


多线程安全问题:两个线程在同时刻,只能其中一个参与运算,另外一个必须等待。
通俗理解:两个同学在餐厅同时抢第一个位置,结果自己想吧!
解决方法:给线程上锁,在这个线程上锁期间,不能有其他线程介入运行,这样就解决问题了!


public class  HelloWorld {
    public static void main(String[] args) {
        new Ticket().start();
        new Ticket().start();
        new Ticket().start();
        new Ticket().start();
    }
}
class Ticket extends Thread{
    private static int ticket = 100;
    public void run(){
        while (true){
            //上锁
            synchronized (Ticket.class){
                if(ticket<=0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;
                }
                System.out.println(getName()+"第"+ ticket-- +"张票售出");
            }
        }
    }
}

线程死锁

/*一个线程持有锁,没释放这个锁之前,其他线程获取不到此锁,
如果其他线程非要此锁,就要死等,这种情况,就是死锁。
*/

线程通讯

等待:wait
单个唤醒:notify
全部唤醒:notifyAll



public class  HelloWorld {
    public static void main(String[] args) {
        Ticket t = new Ticket();
        new Thread(){
            public void run(){
                while (true){
                    try {
                        t.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        new Thread(){
            public void run(){
                while (true){
                    try {
                        t.print2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        new Thread(){
            public void run(){
                while (true){
                    try {
                        t.print3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}
class Ticket {
    private int ticket = 1;
    public void print1() throws InterruptedException {
        synchronized (this){
            if (ticket != 1){
                this.wait();//睡眠
            }
            System.out.println("线程一");
            ticket=2;
            this.notify();//唤醒
        }
    }

    public void print2() throws InterruptedException {
        synchronized (this){
            if (ticket != 2){
                this.wait();//睡眠
            }
            System.out.println("线程二");
            ticket=3;
            this.notify();//唤醒
        }
    }

    public void print3() throws InterruptedException {
        synchronized (this){
            if (ticket != 3){
                this.wait();//睡眠
            }
            System.out.println("线程三");
            ticket=1;
            this.notify();//唤醒
        }
    }
}

线程互斥锁

ReentrantLock 
Condition
/*
 * 互斥锁是JDK1.5版本的新特性,包含了多线程通讯、多线程锁,比起之前的更具有灵活性。
 * 
 * */

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class  HelloWorld {
    public static void main(String[] args) {
        Ticket t = new Ticket();
        new Thread(){
            public void run(){
                while (true){
                    try {
                        t.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        new Thread(){
            public void run(){
                while (true){
                    try {
                        t.print2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        new Thread(){
            public void run(){
                while (true){
                    try {
                        t.print3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}
class Ticket {
    private ReentrantLock r = new ReentrantLock();//互斥锁
    private Condition c1 = r.newCondition();//通讯1
    private Condition c2 = r.newCondition();//通讯2
    private Condition c3 = r.newCondition();//通讯3
    private int ticket = 1;
    public void print1() throws InterruptedException {
        r.lock();//启动锁
            if (ticket != 1){
                c1.await();//等待
            }
            System.out.println("线程一");
            ticket=2;
            c1.signal();//唤醒
        r.unlock();//关闭锁
    }

    public void print2() throws InterruptedException {
        r.lock();//启动锁
            if (ticket != 2){
                c2.await();//睡眠
            }
            System.out.println("线程二");
            ticket=3;
            c2.signal();//唤醒
        r.unlock();//关闭锁
    }

    public void print3() throws InterruptedException {
        r.lock();//启动锁
            if (ticket != 3){
                c3.await();//睡眠
            }
            System.out.println("线程三");
            ticket=1;
            c3.signal();//唤醒
        r.unlock();//关闭锁
    }
}

线程组

//线程组:安全第一,A在1线程组内,A就不能修改2线程组数据。
//线程池:效率第一,A线程干完活,不结束他,让他睡眠,需要再唤醒。
package exercise;
public class exercise {
    public static void main(String[] args) {
        ThreadGroup tg = new ThreadGroup("我是一个新线程");//创建线程组
        MyRunnable mr = new MyRunnable();//创建Runnable的子类对象
        Thread t1= new Thread(tg,mr,"张三");//将线程t1放在组中
        Thread t2= new Thread(tg,mr,"李四");//将线程t2放在组中
        System.out.println(t1.getThreadGroup().getName());//获取组名
        System.out.println(t2.getThreadGroup().getName());
    }
}
class MyRunnable implements Runnable{
    public void run() {
        for(int i=0;i<100;i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }
}

线程池

//一般我们创建少量线程,并不会出现太大问题,可是实际开发中我们
//可能要用到n多线程,频繁创建和销毁线程会严重销毁系统资源,
//针对这一问题,出现了线程池技术,线程池可以对线程回收再利用
package exercise;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class exercise {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(2);//第四步,创建线程池对象
        pool.submit(new MyRunnable());//第五步,将线程放到池子里
        pool.submit(new MyRunnable());
        pool.shutdown();//第六步,关闭线程池
    }
}
class MyRunnable implements Runnable{//第一步
    public void run() {//第二步
        for(int i=0;i<100;i++) {//第三步
            System.out.println(Thread.currentThread().getName());
        }
    }
}

线程生命周期


基础4-高级-多线程_第1张图片
123.png

线程定时器(Timer)

package exercise;
import java.io.IOException;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
class exercise {
    @SuppressWarnings("deprecation")
    public static void main(String[] args) throws IOException, InterruptedException {
        Timer t = new Timer();//第四步,创建计数器
        t.schedule(new Time(), new Date(118,8,0,20,28,00));//new time();时间到了显示起床啦
        //new Data();设定时间
        //年是2018-1900年
        //月是9月
        //日是1日
        //时分秒 21点 23分 00秒
        while(true) {//设定时间
            Thread.sleep(1000);
            System.out.println(new Date());
        }
    }
}
class Time extends TimerTask{//第一步
    public void run() {//第二步
        System.out.println("起床啦");//第三步
    }
}

你可能感兴趣的:(基础4-高级-多线程)