欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

新手了解java 多线程基础知识(二)

程序员文章站 2022-03-08 19:58:39
目录jdk中用thread.state类定义了线程的几种状态:3、lock锁一、线程的生命周期jdk中用thread.state类定义了线程的几种状态:要想实现多线程,必须在主线程中创建新的线程对象。...

一、线程的生命周期

jdk中用thread.state类定义了线程的几种状态:

要想实现多线程,必须在主线程中创建新的线程对象。java语言使用 thread类及其子类的对象来表示线程,在它的一个完整的生命周期中通常 要经历如下的五种状态:

  • 新建:当一个thread类或其子类的对象被声明并创建时,新生的线程 对象处于新建状态;
  • 就绪:处于新建状态的线程被start()后,将进入线程队列等待cpu时间 片,此时它已具备了运行的条件,只是没分配到cpu资源;
  • 运行:当就绪的线程被调度并获得cpu资源时,便进入运行状态, run()方法定义了线程的操作和功能;
  • 阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出 cpu 并临时中止自己的执行,进入阻塞状态;
  • 死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常 导致结束。 在上面五个阶段中,只有新建和死亡是不可重复,其它几个状态都可能改变。

新手了解java 多线程基础知识(二)

注意:

1.新建和死亡状态只能有一次;

2.运行状态只能是从就绪状态变过来的;

3.阻塞状态不能直接变为运行状态,需要通过就绪状态;

4.当一个运行状态的线程调用yield()方法后,就会变为就绪状态;

5.当一个运行状态的线程调用sleep()、等待同步锁方法、wait()方法或 join()方法时,就会处理阻塞状态;

6.当一个阻塞状态的线程调用notify()/notifyall()方法,或者sleep()方法 结束,再或者获得同步锁,或者join()线程执行完毕就可以变为就绪状 态的线程

7.当一个线程执行过多后就处理死亡状态,即线程生命周期结束。

二、线程同步

1、为什么要有线程同步

为了解决线程安全问题,在多线程下,多个线程对一个数据进行修改时,可能会产生数据出错的问题,所以我们就需要通过线程同步的方法来解决问题。

java中的线程同步实现方式:

2、synchronized

2.1同步代码块

示例:

public class myrunnabletest {
    public static void main(string[] args) {
        myrunnable myrunnable = new myrunnable();

        thread thread = new thread(myrunnable,"a");
        thread thread1 = new thread(myrunnable,"b");
        thread thread2 = new thread(myrunnable,"c");
        thread thread3 = new thread(myrunnable,"d");
        thread thread4 = new thread(myrunnable,"e");
        thread.start();
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

    }
    public class myrunnable implements runnable{
        @override
        public void run() {
            synchronized (thread.class){
                system.out.println(thread.currentthread().getname()+"在过山洞");
                try {
                    thread.sleep(300);
                } catch (interruptedexception e) {
                    e.printstacktrace();
                }
            }
        }

注意: 同步锁可以是任意对象,但该对象必须唯一; 同步代码块所在位置也很重要,同步代码块需要把引起数据问题的所有代码都包裹起,不能多裹,也不能少裹。 我们通常都是使用字节码文件来作为同步锁。

2.2同步方法

示例:

public class myrunnabletest {
    public static void main(string[] args) {
        myrunnable myrunnable = new myrunnable();

        thread thread = new thread(myrunnable,"a");
        thread thread1 = new thread(myrunnable,"b");
        thread thread2 = new thread(myrunnable,"c");
        thread thread3 = new thread(myrunnable,"d");
        thread thread4 = new thread(myrunnable,"e");
        thread.start();
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

    }
    public class myrunnable implements runnable{
        @override
        public void run() {
            test()
        }
 public synchronized void test(){
        system.out.println(thread.currentthread().getname()+"在过山洞");
        try {
             thread.sleep(300);
            } catch (interruptedexception e) {
                e.printstacktrace();
            }
        }
    }

**注意:**当使用同步方法来处理多线程的共享数据问题,如果是静态方法,使用的是类名.class方式,如果是非静态方法,使用的是this。

3、lock锁

使用lock.lock()进行加锁操作,然后使用lock.unlock()方法来进行 解锁。

lock是一个接口,不能直接实例化,需要使用子类来实例化,通常使用的 子类是reentrantlock。

public class myrunnabletest {
    public static void main(string[] args) {
        myrunnable myrunnable = new myrunnable();
        thread thread = new thread(myrunnable,"a");
        thread thread1 = new thread(myrunnable,"b");
        thread thread2 = new thread(myrunnable,"c");
        thread thread3 = new thread(myrunnable,"d");
        thread thread4 = new thread(myrunnable,"e");
        thread.start();
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

    }
}
public class myrunnable implements runnable{
    lock lock = new reentrantlock();
        lock.lock();
        system.out.println(thread.currentthread().getname()+"在过山洞");
        try {
                thread.sleep(3000);
            } catch (interruptedexception e) {
                e.printstacktrace();
            }finally {
            lock.unlock();
        }
        }
    }

说明:

在需要作同步操作的代码块之前需要使用lock.lock()方法来作加锁处 理;在同步操作的代码块之后,增加finally语句块来释放锁,释放锁的方法为lock.unlock()方法;一定要确保锁能释放,否则就是死锁;

lock比synchronized更轻量级,功能更强大,如果可以尽量使用lock。

总结

本篇文章就到这里了,希望对你有所帮助,也希望你能够多多关注的更多内容!