文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java如何实现多线程、线程同步

2023-06-30 10:45

关注

这篇文章主要介绍了Java如何实现多线程、线程同步的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java如何实现多线程、线程同步文章都会有所收获,下面我们一起来看看吧。

Java如何实现多线程、线程同步

1 多线程

1.1 进程

1.2 线程

1.3 多线程的实现方式

1.3.1 方式1:继承Tread类
package test;//1、定义一类MyTread继承Tread类public class MyThread extends Thread{    2、在MyTread类中重写run()方法    @Override    public void run() {        for(int i=0;i<100;i++) {            System.out.println(i);        }    }}
package test;public class Demo {    public static void main(String[] args) {        //3、创建MyTread类的对象        MyThread my1 = new MyThread();        MyThread my2 = new MyThread();        //4、启动线程:void start():启动线程,由Java虚拟机调用此线程的run()方法        my1.start();        my2.start();    }}
1.3.2 方式2:实现Runnable接口
package test;public class Demo {    public static void main(String[] args) {        //3、创建MyRunnable类的对象        MyRunnable mr = new MyRunnable();        //4、创建Tread类的对象,把MyRunnable对象作为构造方法的参数//        Thread t1 = new Thread(mr);//        Thread t2 = new Thread(mr);        //Thread(Runnable target,String name)        Thread t1 = new Thread(mr,"高铁");        Thread t2 = new Thread(mr,"飞机");        //5、启动线程        t1.start();        t2.start();    }}
1.3.3 方式3:实现Callable接口

1.4 设置和获取线程名称

方法名说明
void setName(Stringname)将此线程的名称更改为等于参数name
String getName()返回此线程的名称
public Thread(String name)通过构造方法也可以设置线程名称
public static Thread currentThread()返回对当前正在执行的线程对象的引用(可以返回main()方法中线程)
public static void sleep(long time)让当前线程休眠多少毫秒再继续执行
package test;public class MyThread extends Thread{    //构造方法添加线程名称    public MyThread(){}    public MyThread(String name) {        super(name);    }        @Override    public void run() {        for(int i=0;i<100;i++) {            //1,String getName() 返回此线程的名称            System.out.println(getName()+":"+i);        }    }}
package test;public class Demo {    public static void main(String[] args) {                        //3,通过构造方法设置线程名称        //需要自己定义的类中提供此带参构造方法,并通过super访问父类带参构造方法                        //4,public static Thread currentThread() 返回对当前正在执行的线程对象的引用(可以返回main()方法中线程)        System.out.println(Tread.currentThread().getName()); //main    }}

1.5 线程调度

方法名说明
public final int getPriority() [praɪˈɔːrəti]返回此线程的优先级
public final void setPriority(int newPriority)更改此线程的优先级
package test;public class Demo {    public static void main(String[] args) {        ThreadPriority tp1 = new ThreadPriority();        ThreadPriority tp2 = new ThreadPriority();        ThreadPriority tp3 = new ThreadPriority();        tp1.setName("高铁");        tp2.setName("飞机");        tp3.setName("汽车");        //1,public final int getPriority() [praɪˈɔːrəti] 返回此线程的优先级//        System.out.println(tp1.getPriority()); //5//        System.out.println(tp2.getPriority()); //5//        System.out.println(tp3.getPriority()); //5        //2,public final void setPriority(int newPriority) 更改此线程的优先级        System.out.println(Thread.MAX_PRIORITY); //10        System.out.println(Thread.MIN_PRIORITY); //1        System.out.println(Thread.NORM_PRIORITY); //5        //设置正确优先级        tp1.setPriority(5);        tp2.setPriority(10);        tp3.setPriority(1);        tp1.start();        tp2.start();        tp3.start();    }}

1.6 线程控制

方法名说明
static void sleep(long millis)使当前正在执行的线程停留(暂停执行)指定的毫秒数
void join()等待这个线程死亡
void setDaemon(boolean on) [ˈdiːmən]将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机很快将退出 (并不是立刻退出)

案例:sleep()方法

package test;public class ThreadSleep extends Thread{    @Override    public void run() {        for(int i=0;i<10;i++) {            System.out.println(getName()+":"+i);            //1,static void sleep(long millis) 使当前正在执行的线程停留(暂停执行)指定的毫秒数            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}
package test;public class Demo {    public static void main(String[] args) {        ThreadSleep ts1 = new ThreadSleep();        ThreadSleep ts2 = new ThreadSleep();        ThreadSleep ts3 = new ThreadSleep();        ts1.setName("曹操");        ts2.setName("刘备");        ts3.setName("孙权");        ts1.start();        ts2.start();        ts3.start();//        曹操:0//        孙权:0//        刘备:0//        孙权:1//        曹操:1//        刘备:1//        ...    }}

案例:join()方法

package test;public class Demo {    public static void main(String[] args) {        ThreadJoin tj1 = new ThreadJoin();        ThreadJoin tj2 = new ThreadJoin();        ThreadJoin tj3 = new ThreadJoin();        tj1.setName("康熙");        tj2.setName("四阿哥");        tj3.setName("八阿哥");        tj1.start();        //2,void join() 等待这个线程死亡        try {            tj1.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        tj2.start();        tj3.start();//        康熙:0//        康熙:1//        康熙:2//        四阿哥:0//        四阿哥:1//        八阿哥:0//        八阿哥:1//        八阿哥:2//        四阿哥:2//        ...    }}

案例:setDaemon()方法

package test;public class Demo {    public static void main(String[] args) {        ThreadJoin tj1 = new ThreadJoin();        ThreadJoin tj2 = new ThreadJoin();        ThreadJoin tj3 = new ThreadJoin();        tj2.setName("关羽");        tj3.setName("张飞");        //设置主线程为刘备        Thread.currentThread().setName("刘备");        //3,void setDaemon(boolean on) 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出        tj1.setDaemon(true);        tj2.setDaemon(true);        tj1.start();        tj2.start();        for(int i=0;i<2;i++) {            System.out.println(Thread.currentThread().getName()+":"+i);        }        //刘备执行完后,关羽和张飞会很快结束    }}

1.7 线程生命周期

Java如何实现多线程、线程同步

1.8 数据安全问题之案例:买票

Java如何实现多线程、线程同步
Java如何实现多线程、线程同步

1.9 线程同步_同步代码块

synchronized(任意对象) {多条语句操作共享数据的代码}
package test;//1,定义一个类SellTicket实现Runnable接口,里面定义一个成员变量: private int tickets= 100;public class SellTicket implements Runnable{    private int tickets = 100;    private Object obj = new Object();    //2,在ellTicket类中重写run0方法实现卖票, 代码步骤如下    @Override    public void run() {        while(true) {            //tickes=100            //t1,t2,t3            //假设t1抢到CPU执行器            synchronized (obj){                //t1进来后把代码锁起来了                if (tickets > 0) {                    try {                        Thread.sleep(100);                        //t1休息100毫秒                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    //窗口1正在出售第100张票                    System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");                    tickets--; //tickets=99                }                //t1出来了,锁就被释放了            }        }    }}
package test;public class SellTicketDemo {    public static void main(String[] args) {        //创建SellTicket类的对象        SellTicket st = new SellTicket();        //创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称        Thread t1 = new Thread(st,"窗口1");        Thread t2 = new Thread(st,"窗口2");        Thread t3 = new Thread(st,"窗口3");        //启动线程        t1.start();        t2.start();        t3.start();    }}

1.10 线程同步_同步方法

package test;public class SellTicket implements Runnable{//1非静态    private int tickets = 100;    private static int tickets = 100;    private Object obj = new Object();    private int x = 0;    @Override    public void run() {        while(true) {            if(x%2==0) {//1非静态                synchronized (this) {                synchronized (SellTicket.class) {                    if (tickets > 0) {                        try {                            Thread.sleep(100);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                        System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");                        tickets--; //tickets=99                    }                }            } else {//                synchronized (obj) {//                    if (tickets > 0) {//                        try {//                            Thread.sleep(100);//                        } catch (InterruptedException e) {//                            e.printStackTrace();//                        }//                        System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");//                        tickets--; //tickets=99//                    }//                }                sellTicket();            }            x++;        }    }//1非静态//    private synchronized void sellTicket() {//        if (tickets > 0) {//            try {//                Thread.sleep(100);//            } catch (InterruptedException e) {//                e.printStackTrace();//            }//            System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");//            tickets--; //tickets=99//        }//    }    private static synchronized void sellTicket() {        if (tickets > 0) {            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");            tickets--; //tickets=99        }    }}

1.11 线程安全的类(了解)

源码中方法都被synchronized修饰

StringBuffer

Vector

Hashtable

Collections类中static <T> List<T> snchronizedList(List<T> list):返回由指定列表支持的同步(线程安全)的列表

package test;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;public class Demo {    public static void main(String[] args)  {        //static <T> List<T> snchronizedList(List<T> list):返回由指定列表支持的同步(线程安全)的列表        Collection<String> list = Collections.synchronizedList(new ArrayList<String>());            }}

1.12 Lock锁

方法名说明
ReentrantLock()创建一个ReentrantLock的实例对象
方法名说明
void lock()获得锁
void unlock()释放锁
package test;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class SellTicket implements Runnable{    private static int tickets = 100;    private Lock lock = new ReentrantLock();    @Override    public void run() {        while(true) {            try {                lock.lock();                if (tickets > 0) {                    try {                        Thread.sleep(100);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");                    tickets--;                }            }finally {                lock.unlock();            }        }    }}

1.13 线程通讯

方法名说明
public void wait()让当前线程进入到等待状态,此方法必须锁对象调用
public void notify()唤醒当前锁对象上等待状态的某个线程,此方法必须锁对象调用
public void notifyAll()唤醒当前锁对象上等待状态的全部线程,此方法必须锁对象调用

1.14 生产者消费者

1.14.1 生产者消费者概述

Java如何实现多线程、线程同步

方法名说明
void wait()导致当前线程等待,直到另一个线程调用该对象的 notify() 方法或 notifyAll() 方法
void notify()唤醒正在等待对象监视器的单个线程
void notifyAll()唤醒正在等待对象监视器的所有线程
1.14.2 生产者消费者案例

Java如何实现多线程、线程同步

package test;//1:定义奶箱类public class Box {    //定义一个成员变量,表示第x瓶奶    private int milk;    //定义一个成员变量表示奶箱的状态    private boolean state = false;    //提供存储牛奶和获取牛奶的操作    public  synchronized void put(int milk) {        //如果有牛奶等待消费        if(state) {            try {                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        //如果没有牛奶,就生产牛奶        this.milk = milk;        System.out.println("送奶工将第" + this.milk + "瓶奶放入奶箱");        //生产完毕后,修改奶箱状态        state = true;        //唤醒其他等待线程        notifyAll();    }    public  synchronized void get() {        //如果没有牛奶,就等到生产        if(!state) {            try {                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        //如果有牛奶,就消费牛奶        System.out.println("用户拿到第" + this.milk + "瓶奶");        //消费完毕后,修改奶箱状态        state = false;        //唤醒其他等待线程        notifyAll();    }}
package test;//2:生产者类(Producer):实现Runnable接口public class Producer implements Runnable {    private Box b;    public Producer(Box b) {        this.b = b;    }    //重写run()方法,调用存储牛奶的操作    @Override    public void run() {        for (int i = 1; i <= 5; i++) {            b.put(i);        }    }}
package test;//3:消费者类(Customer);实现Runnable接口public class Customer implements Runnable{    private Box b;    public Customer(Box b) {        this.b = b;    }    //重写run()方法,调用获取牛奶的操作    @Override    public void run() {        while(true) {            b.get();        }    }}
package test;public class BoxDemo {    public static void main(String[] args) {        //创建奶箱对象,这是共享数据区域        Box b = new Box();        //创建生产者对象,把奶箱对象作为构造方法参数传递。因为在这个类中要谓用存储牛奶的操作        Producer p = new Producer(b);        //创建消费者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用获取牛奶的操作        Customer c  =new Customer(b);        //创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递        Thread t1 = new Thread(p);        Thread t2 = new Thread(c);        //启动线程        t1.start();        t2.start();//        送奶工将第1瓶奶放入奶箱//                用户拿到第1瓶奶//        送奶工将第2瓶奶放入奶箱//                用户拿到第2瓶奶//        送奶工将第3瓶奶放入奶箱//                用户拿到第3瓶奶//        送奶工将第4瓶奶放入奶箱//                用户拿到第4瓶奶//        送奶工将第5瓶奶放入奶箱//                用户拿到第5瓶奶    }}

关于“Java如何实现多线程、线程同步”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Java如何实现多线程、线程同步”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯