Java multithreading and solving thread synchronization problems

Process: Threads are inseparable from processes. Let me talk about what a process is! (Open the Explorer, we can see the currently running process).

Thread: It is a single sequential control flow in a process and an execution path.

Single-threaded: If a process has only one execution path, it becomes a single-threaded program.

Multithreading: If a process has multiple execution paths, it becomes a multithreaded program.

Implement multithreading

方式一:继承Thread类
1.定义一个类MyThread 继承Thread类
2.在MyThread类中重写Run()方法
3.创建对象
4.启动线程  用Start方法
public class MyThread extends Thread {
    @Override
    public void run() {
       for (int i=0;i<100;i++){
           System.out.println(i);

       }
    }
}

public class MyThreadDemo {
    public static void main(String[] args) {
        MyThread m1=new MyThread();
        MyThread m2=new MyThread();
        m1.start();
        m2.start();
    }
}
方法2:实现Runnable接口
定义一个MyRunnable类,实现Runnable接口
在MyRunnable类中重写run方法
创建MyRunnable类的对象
创建Thread类对象,将MyRunnable对象作为构造方法的参数
启动线程

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



public class MyRunnableDemo {
    public static void main(String[] args) {
        MyRunnable my=new MyRunnable();
        Thread t1=new Thread(my);
        Thread t2=new Thread(my);
        t1.start();
        t2.start();
    }

}

Question: Why rewrite the run() method?

The run method is used to encapsulate the code executed by the thread.

What is the difference between run() method and start() method?

run(): Encapsulate the code executed by the thread and call it directly, which is equivalent to the call of an ordinary method.

start(): Start the thread, and then the run() method of this thread is called by the JVM.

Set and get the thread name

   public static void main(String[] args) {
        MyThread m1=new MyThread();
        m1.setName("王");
        String name = m1.getName();
        System.out.println(name);
    }

Thread scheduling

 Java uses preemptive scheduling: threads with high priority use CPU first. With the same priority, one will be randomly selected. A thread with a higher priority gets a little more CPU time slice.

        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();
        MyThread m3 = new MyThread();
//获取线程的优先级,优先级默认是5,最高是10,最小是1.
//        System.out.println(m1.getPriority());//5
//        System.out.println(m2.getPriority());//5
//        System.out.println(m3.getPriority());//5

//更改线程的优先级
        m1.setPriority(1);
        m2.setPriority(10);
        m3.setPriority(1);

Thread control

//Thread.sleep(); 使当前正在执行的线程停留,指定的秒数,然后继续执行。

//vodi join();等待这个线程死亡。
//下面例子,m1,结束后,m2,m3才运行。
        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();
        MyThread m3 = new MyThread();
 
        m1.setName("王");
        m2.setName("李");
        m3.setName("孙");
   m1.start();
        try {
            m1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        m2.start();
        m3.start();


//void setDaemon(boolean on) 将此线程标记为守护线程,运行的线程都是守护线程时,java虚拟机将退出。
//例子:当主线程刘备结束后,关羽和张飞也退出线程。

        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();
        
        m1.setName("关羽");
        m2.setName("张飞");
        Thread.currentThread().setName("刘备");
        m1.setDaemon(true);
        m2.setDaemon(true);
        m1.start();
        m2.start();
        for (int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }

Thread life cycle

 Thread synchronization 

Case: Ticket buying system, 3 windows buy tickets at the same time, and then use multiple threads.

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

public class SellTickerDmo {
    public static void main(String[] args) {
        SellTicket st=new 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();
    }
}

The above writing will cause problems, it is a ticket, sold many times. What we need is to lock multiple statements that operate on shared data, that is, lock them, and only one can access them at a time.

Synchronous code block method to solve the problem:

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

Lock to solve the synchronization problem: 

Lock is an interface and cannot be directly instantiated and used. Its implementation class ReentrantLock can be used. 

The main method is to obtain the lock and cast the lock.

public class SellTicket  implements Runnable{
    private  int tickets=1000;
    private Lock lock =new ReentrantLock();
    @Override
    public void run() {
        while(true){
            try{
                lock.lock();
                if (tickets>0){
                    try{
                        Thread.sleep(10);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"zhang票");
                    tickets--;
                }
            }finally {
                lock.unlock();
            }
        }
    }
}

Thread-safe classes:

If you need to perform synchronization and ensure thread safety, you can use the following classes. Their underlying methods are all locked with  synchronized .

        StringBuffer sbf=new StringBuffer(); 
//下面这两个是线程安全的集合,但是我们一般不会去用。用下面的方法转!
        Vector ve=new Vector();
        Hashtable ht=new Hashtable();

//下面方法可以把集合转成 线程安全的。
List<String> list = Collections.synchronizedList(new ArrayList<String>());

 

Guess you like

Origin blog.csdn.net/weixin_44126152/article/details/106373872