基础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());
        }
    }
}

线程生命周期


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("起床啦");//第三步
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容

  • 本文将从以下几个部分来介绍多线程。 第一部分介绍多线程的基本原理。 第二部分介绍Run loop。 第三部分介绍多...
    曲年阅读 1,262评论 2 14
  • 一、进程和线程 进程 进程就是一个执行中的程序实例,每个进程都有自己独立的一块内存空间,一个进程中可以有多个线程。...
    阿敏其人阅读 2,612评论 0 13
  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 2,104评论 0 14
  • 前几天下载了这个软件,今天才突然想起来要好好看看。(还是在上课的时候偷偷看的,专业课太枯燥无聊了)我着重看了一...
    欣然娜拉阅读 405评论 4 3
  • 信用卡是因赊账而出现的。顾客拿着信用卡购物,就是告诉商家我要这东西,但要赊账。赊账需要凭证,凭证就是这张卡。这张卡...
    xxwade阅读 536评论 1 1