Java学习总结——多线程编程

Java多线程编程

一、创建线程的方法一:

继承:extends Thread 重写run()方法

举个栗子🌰:

public class MyThread extends Thread {
    public MyThread() {
        //空的构造方法
    }
    
    //传递name表示线程名字
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (interrupted()) {
                System.out.println("释放资源!");
                break;
            }
            System.out.println(getName()+":"+i);
        }
    }
}

MyThread t1 = new MyThread(“线程一”);
MyThread t2 = new MyThread(“线程二”);

Thread thread = new Thread();
thread.start();//启动线程

thread.getPriority();//获取优先级
thread.setPriority();//设置优先级(1-10)

thread .getName();//获取线程名字
thread .setName();//设置线程名字

线程休眠:

Thread.sleep(4000);//主线程休眠四秒之后再运行

线程加入:

t1.join();//将线程t1加入主线程

设置守护线程:

t2.setDaemon(true);将t2线程设置为守护线程(守护线程需要在线程启动之前设置),守护线程是为守护其他线程而存在,如果其他所有线程都运行完之后,只还剩下守护线程没运行完,那么守护线程将自动销毁!

线程的中断:

t1.interrupt();//手动处理线程中断
interrupted();//将返回布尔值

线程的生命周期:

二、创建线程的方法二:

实现Runnable接口: implement Runnable

public class RunnableThread implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            Thread thread = Thread.currentThread();//获取当前线程名字
            System.out.println(thread.getName()+":"+i);
        }
        
    }

}

该方法不能直接使用start()方法启动线程。 需要使用Thread声明一个对象,再将runnable对象传入Thread对象。

RunnableThread t = new RunnableThread();

Thread t1 = new Thread(t,”线程一”);
t1.start();
        
Thread t2 = new Thread(t,”线程二”);
t2.start();

两种创建线程方法区别: runnable方法只需要创建一个runnable对象,Thread方法需要创建多个MyThread对象。Thread方法获取线程其他参数更方便。两种方法都需要重写run()方法。

使用Runnable方法创建线程的好处:

  1. 可以很方便的实现多线程数据的共享。
  2. 该方法还可以继承其他的类,而继承Thread类的方法不能再继承其他的类了。

三、创建线程的方法三:

匿名内部类
直接在主类里面定义一个Runnable类来实现Runnable接口里面的run()方法。
适用于该线程在主类里面只使用一次的情况,不用再创建一个线程类来实现Runnable接口。
线程安全问题
当多个线程需要同时修改同一共享数据时,产生冲突,就会出现线程安全问题。

  1. 加锁解决:
private Object lock = new Object();//需要声明一个对象作为锁
//加锁
synchronized (lock) {
    //需要加锁执行的代码
}//执行完毕,归还钥匙

也可以直接使用同步方法:sellTicket()

public synchronized void sellTicket(){
//需要加锁的代码
}//相当于给这个方法加了锁

同步方法不需要再声明一个对象作为锁了。

  1. 使用专门的锁对象ReentrantLock来加锁:
private ReentrantLock lock = new ReentrantLock();
lock.lock();//加锁
//需要加锁的代码
lock.unlock();//解锁

死锁问题的解决:

多个线程以相同的顺序去取锁,取到所有锁之后才执行需要加锁的代码!

举个栗子🌰:

public class DeadLock {
    //创建两把锁
    public static Object lock1 = new Object();
    public static Object lock2 = new Object();
    
    public static void main(String[] args) {
        //启动两个线程
        new Thread(new Thread1()).start();
        new Thread(new Thread2()).start();
    }
}
//匿名内部类实现Runnable创建Thread1线程
class Thread1 implements Runnable{
    
    @Override
    public void run() {
        synchronized (DeadLock.lock1) {//先取第一把锁
            System.out.println("Thread1取得了第一把锁之后要做的事情");
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            synchronized (DeadLock.lock2) {//再取第二把锁
                System.out.println("Thread1同时取得两把锁之后要做的事情");
            }
        }
    }
    
}

//匿名内部类实现Runnable创建Thread2线程
class Thread2 implements Runnable{

    @Override
    public void run() {
        synchronized (DeadLock.lock1) {//先取第一把锁
            System.out.println("Thread2取得了第二把锁之后要做的事情");
            synchronized (DeadLock.lock2) {//再取第二把锁
                System.out.println("Thread2同时取得两把锁之后要做的事情");
            }
        }
    }
    
}

创建线程组:ThreadGroup

ThreadGroup tg = new ThreadGroup(“我的线程组”);
定时器:Timer

需要在计时器任务里面设置任务:TimerTask

Timer timer = new Timer();//定时器
timer.schedule(new MyTimer(), 2000);//2s后启动计时器任务
timer.schedule(new MyTimer(), 2000, 1000);//2s启动后,隔3s后再重复执行计时器任务
timer.cancel();//取消定时器

举个栗子🌰:

public class Demo_Timer {
    public static void main(String[] args) {
        Timer timer = new Timer();//定时器
        
        //timer.schedule(new MyTimer(), 2000);
        timer.schedule(new MyTimer(), 2000, 1000);
        //timer.cancel();//取消定时器
        
    }
}

//定时器任务(匿名内部类)
class MyTimer extends TimerTask{

    @Override
    public void run() {
        System.out.println("定时器任务..");
    }
        
}

四、综合实例:

电影院售票问题: 说明:两种买票方式,手机APP端和电影院窗口端同时售票,采用创建多线程的方式来解决电影票多端售出产生的冲突!

采用实现Runnable接口的方法创建线程。

1、创建AppThread类:(APP端线程类)

public class AppThread implements Runnable {
    private Object lock;
    
    public AppThread(Object lock) {
        this.lock = lock;
    }
    
    @Override
    public void run() {
        while (MovieTicketManage.count>0) {
            synchronized (lock) {
                if (MovieTicketManage.count>0) {
                    System.out.println(Thread.currentThread().getName()+"售出了第"+MovieTicketManage.count+"张电影票..");
                    MovieTicketManage.count--;
                }
            }
            
            try {
                Thread.sleep(0);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }

}

2、创建WindowThread类:(window端线程类)

public class WindowThread implements Runnable {
    private Object lock;
    
    public WindowThread(Object lock) {
        this.lock = lock;
    }
    
    @Override
    public void run() {
        while (MovieTicketManage.count>0) {
            synchronized (lock) {
                if (MovieTicketManage.count>0) {
                    System.out.println(Thread.currentThread().getName()+"售出了第"+MovieTicketManage.count+"张电影票..");
                    MovieTicketManage.count--;
                }
            }
            
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }

    }

}

3、创建MovieTicketManage类:(票管理类,存储电影票数量,为了多线程数据的共享)

public class MovieTicketManage {
    public static int count = 100;
}

4、创建CinemaSale主类:(电影票售票主类)

public class CinemaSale {
    public static void main(String[] args) {
        Object lock = new Object();
        
        WindowThread windowThread = new WindowThread(lock);
        AppThread appThread = new AppThread(lock);
        
        new Thread(windowThread,"窗口").start();
        new Thread(appThread,"APP手机").start(); 
    }
}

需要创建一把相同的锁lock,将这把锁传入AppThread和WindowThread线程类,保证锁的唯一,如果在AppThread线程和WindowThread线程里面创建锁,那么就是不同对象的锁了。就不能保证共享数据的同步,通过定义一个成员变量lock,通过构造方法将这个锁传递过来.

这样在购买电影票的时候就不会产生线程冲突和死锁问题了!

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

推荐阅读更多精彩内容

  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 2,921评论 1 18
  • 文章来源:http://www.54tianzhisheng.cn/2017/06/04/Java-Thread/...
    beneke阅读 1,442评论 0 1
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,376评论 1 15
  •   一个任务通常就是一个程序,每个运行中的程序就是一个进程。当一个程序运行时,内部可能包含了多个顺序执行流,每个顺...
    OmaiMoon阅读 1,629评论 0 12
  • 林炳文Evankaka原创作品。转载自http://blog.csdn.net/evankaka 本文主要讲了ja...
    ccq_inori阅读 617评论 0 4