【java笔记】进程和线程:线程同步,Lock锁

进程:正在运行的程序
线程:执行路径
单线程程序:记事本
多线程程序:扫雷
多线程的实现方式:

package demo06;
/*
多线程的实现方法
1.定义Thread类重写run方法
2.创建Thread类的对象
3.启动多线程
*/
public class Demo01 {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        my1.start();
        my2.start();
    }
}

package demo06;
/*
创建一个新的执行线程有两种方法。 一个是将一个类声明为一个Thread的子类。 这个子类应该重写Thread类的方法run 。
 */
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}

设置和获取线程名称:

package demo06;
/*
设置和获取线程名称:
 1.getName​() 返回此线程的名称。
 2.setName​(String name) 将此线程的名称更改为等于参数 name 。
 3.static Thread currentThread​() 返回对当前正在执行的线程对象的引用。
*/
public class Demo01 {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        my1.setName("飞机");
        my2.setName("高铁");
        my1.start();
        my2.start();
        System.out.println(Thread.currentThread());
    }
}

package demo06;
/*
创建一个新的执行线程有两种方法。 一个是将一个类声明为一个Thread的子类。 这个子类应该重写Thread类的方法run 。
 */
public class MyThread extends Thread {
    public void MyThread(){};
    public void MyThread(String name){};

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":"+i);
        }
    }
}

多线程设置和获取优先级

package demo06;
/*
线程调度和线程优先级
1.int getPriority​() 返回此线程的优先级。
2.void setPriority​(int newPriority) 更改此线程的优先级。  优先级的范围1-10
注:优先级高只能表示调用CPU的几率高
*/
public class Demo01 {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        MyThread my3=new MyThread();
        my1.setName("飞机");
        my2.setName("高铁");
        my3.setName("汽车");

        my1.setPriority(10);
        my2.setPriority(5);
        my3.setPriority(1);

        my1.start();
        my2.start();
        my3.start();
    }
}

线程控制sleep

package demo06;
/*
线程控制
1.static void sleep​(long millis) 使当前正在执行的线程停留(暂停执行)指定的毫秒数,这取决于系统定时器和调度程序的精度和准确性。
 */
public class MyThread extends Thread {
    public void MyThread(){};
    public void MyThread(String name){};

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":"+i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程控制join:

package demo06;
/*
线程控制
2.void join​() 等待这个线程死亡。  
*/
public class Demo01 {
    public static void main(String[] args) throws InterruptedException {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        MyThread my3=new MyThread();
        my1.setName("飞机");
        my2.setName("高铁");
        my3.setName("汽车");
        

        my1.start();
        my1.join();
        my2.start();
        my3.start();
    }
}

线程控制3守护线程

package demo06;
/*
线程控制
3.void setDaemon​(boolean on) 将此线程标记为 daemon线程或用户线程。  守护线程
*/
public class Demo01 {
    public static void main(String[] args) throws InterruptedException {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        MyThread my3=new MyThread();
        my1.setName("关羽");
        my2.setName("张飞");
        //设置主线程
        Thread.currentThread().setName("刘备");
        //设置守护线程
        my1.setDaemon(true);
        my2.setDaemon(true);


        my1.start();
        my2.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+","+i);

        }
    }
}

线程的生命周期
在这里插入图片描述
多线程的第二种实现方法:

package demo06;
/*
多线程的第二种实现方法:
1.定义一个类MyRunnable实现runnable接口
2.重写run方法
3.创建MyRunnable对象
4.创建Thread对象,将MyRunnable对象作为Thread对象的参数
5.启动线程
 */
public class Demo02 {
    public static void main(String[] args) {
        MyRunnable mr=new MyRunnable();
        MyRunnable mr2=new MyRunnable();
        Thread th1=new Thread(mr,"飞机");
        Thread th2=new Thread(mr2,"高铁");

        th1.start();
        th2.start();

    }
}

第二种方法的优点:
(1)解决java单继承的问题
(2)体现面向对象的思想,把线程和程序有效分离

卖票案例

package demo06;
/*
案例:卖票
 */
public class Demo03 {
    public static void main(String[] args) {
        SellTicket st=new SellTicket();
        Thread th1=new Thread(st,"窗口1");
        Thread th2=new Thread(st,"窗口2");
        Thread th3=new Thread(st,"窗口3");
        th1.start();
        th2.start();
        th3.start();
    }
}

package demo06;

public class SellTicket implements Runnable {
    private int ticket=100;
    @Override
    public void run() {
        while (true){
            if(ticket>0){
                System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket+"张票");
                ticket--;
            }
        }
    }
}

卖票案例的思考:

package demo06;
/*
案例:卖票案例的思考
使用Thread.sleep后
出现负数票和同一张票卖多次的现象
原因:线程的随机性
一票卖多次:在ticket--之前被另一个线程抢到CPU
负数票:在ticket--之后被另一个线程抢到CPU
 */
public class Demo03 {
    public static void main(String[] args) {
        SellTicket st=new SellTicket();
        Thread th1=new Thread(st,"窗口1");
        Thread th2=new Thread(st,"窗口2");
        Thread th3=new Thread(st,"窗口3");
        th1.start();
        th2.start();
        th3.start();
    }
}

  1. 线程同步
    synchronized解决数据安全问题:
package demo06;

public class SellTicket implements Runnable {
    private int ticket=100;
    Object obj=new Object();
    @Override
    public void run() {
        while (true){
            synchronized (obj){
            if(ticket>0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket+"张票");
                ticket--;
            }
        }
}
}}

优点:各个线程分开
缺点:各个线程都会去判断同步上的锁,耗费资源

同步方法的锁对象:this

package demo06;

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

    private synchronized void sellTicket() {
  
            if(ticket>0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket+"张票");
                ticket--;
            }
        }


    }


静态同步方法的锁对象:类名.class

package demo06;

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

    private synchronized static void sellTicket() {

            if(ticket>0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket+"张票");
                ticket--;
            }
        }


    }


线程安全的类:

package demo06;

import java.util.*;

/*
线程安全的类
StringBuffer
Vector
Hashtable
 */
public class Demo04 {
    public static void main(String[] args) {
        StringBuilder sb=new StringBuilder();
        StringBuffer sbb=new StringBuffer();

        Vector<String> ve=new Vector<>();
        ArrayList<String> arr=new ArrayList<>();

        Hashtable<String,String> ht=new Hashtable<>();
        HashMap<String,Integer> hm=new HashMap<>();

        //更常用的static <T> List<T> synchronizedList​(List<T> list) 返回由指定列表支持的同步(线程安全)列表。
        List<String> strings = Collections.synchronizedList(new ArrayList<String> ());
    }
}

Lock锁:

package demo06;


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

/*
lock的使用:
void lock​() 获得锁。
void unlock​() 释放锁。
构造方法:ReentrantLock​() 创建一个 ReentrantLock的实例。
 */
public class SellTicket implements Runnable {
    private int ticket=100;
    private Lock lock =new ReentrantLock();
    @Override
    public void run() {
        while (true){
                try{
                    lock.lock();
                    if(ticket>0){
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket+"张票");
                        ticket--;
                    }
                }finally {
                    lock.unlock();
                }

            }
        }
    }

生产者和消费者模式概述:
Object类中的等待和唤醒方法:
1.void wait​() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
2.void notify​() 唤醒正在等待对象监视器的单个线程。
3.void notifyAll​() 唤醒正在等待对象监视器的所有线程。

?案例:生产者和消费者案例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值