【JAVA多线程编程核心技术】第一章 Java多线程技能(待补充)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chuxue1989/article/details/88081942

这里仅仅是我读该书收获的知识点,如果我熟悉的我自动或略不写

一、创建方式

java多线程有两种创建方式

  • 继承thread
  • 实现Runnable接口

下面演示实现Runnable接口的创建方式:

Class A implements Runable{
	@Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+":运行了");
            }
}

public static void main(String[] args) {
    A a = new A();
	Thread thread = new Thread(a);
	thread.start();
}

Thread的构造方法中,传递的是Runnable类型,public Thread(Runnable target),而且Thread也是实现Runnable 接口的,所以如果一个类继承了Thread,然后又通过Thread的构造函数传递给new Thread()也是可行的。比如下面的例子:

Class A implements Thread{
	
      public void run() {
           System.out.println(Thread.currentThread().getName()+":运行了");
       }
}

public static void main(String[] args) {
    A a = new A();  //Thread-0
	Thread thread = new Thread(a);//Thread-1
	thread .start();
}

但是通过这种方式,实际上创建了2个线程,第一个就是继承Thread线程,可以通过a.start直接运行,第二个线程就是thread变量代表的线程。下面通过isAlive方法来打印来进一步说明

static class A extends Thread{

        @Override
        public  void run() {
            System.out.println("Thread.currentThread().getName:"+Thread.currentThread().getName());
            System.out.println("this.getName:"+this.getName());

            System.out.println("Thread.currentThread():"+Thread.currentThread().isAlive());
            System.out.println("this.isActive:"+this.isAlive());
        }
    }
    
 public static void main(String[] args) {
        A a = new A();
        Thread t = new Thread(a);
        t.start();
    }

在这里插入图片描述
可知Thread.currentThread()代表了线程1.
this代表了线程0
因为调用的是t.start();所以Thread.currentThread().isAlive()方法返回时true,而this.isAlive()代表线程0返回false

1.1、start和run

调用start方法后通知线程规划器,线程已经准备完毕,等待CPU调度,然后调用对象的run方法。
如果直接调用run方法,根本就没有开启一个线程,而是main线程调用了对象的run方法。



二、线程停止

这部分目前是不完整的,后期会补充

  • 退出标志,正常退出
  • interrupte方法
  • stop

2.1 interrupt方法

不是静态方法,所以他针对的是调用该方法的对象

/**
* Interrupts this thread.
*/

紧紧是在线程中打了一个停止标记,开发者,可以利用这个停止标记通过抛出异常或者return来停止这个线程。
判断线程中断标志的两个方法
interrupted:

官方解释
/**
* Tests whether the current thread has been interrupted. The
* interrupted status of the thread is cleared by this method.
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}

测试当前线程是否被中断,并且清除中断状态。他是个静态方法,所以和调用者无关,他关系的是当前对象是否中断。

isInterrupted:

/**
* Tests whether this thread has been interrupted. The interrupted
* status
of the thread is unaffected by this method.
*/
public boolean isInterrupted() {
return isInterrupted(false);
}

注意他是个非静态方法,所以他是让调用者线程中断,并且不清除中断标志。

下面演示一个经典的通过中断标志来停止线程的

 public static void main(String[] args) {
        try {
            B b = new B();
            b.start();

            Thread.sleep(1000);

            b.interrupt();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


 private static class B extends Thread{

        @Override
        public void run() {
            super.run();
            try {
                for(int i=0;i<500000;i++){

                    if(this.isInterrupted()){
                        System.out.println("线程"+this.getName()+"已经结束");
                        throw new InterruptedException();
                    }

                    System.out.println("i="+i);
                }

                System.out.println("for之外的语句");
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
    

注意sleep+interrupt方法。

/**
* Causes the currently executing thread to sleep (temporarily cease
* execution) for the specified number of milliseconds, subject to
* the precision and accuracy of system timers and schedulers. The thread
* does not lose ownership of any monitors.
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* interrupted status of the current thread is
* cleared when this exception is thrown.
*/
public static native void sleep(long millis) throws InterruptedException;

注意sleep方法会抛出InterruptedException异常,也就是说如果一个线程被打了中断标志,然后执行sleep就会包这个异常。

2.2 stop

这个方法比较暴力。

/*
* @deprecated This method is inherently unsafe. Stopping a thread with
* Thread.stop causes it to unlock all of the monitors that it
* has locked (as a natural consequence of the unchecked
* ThreadDeath exception propagating up the stack). If
* any of the objects previously protected by these monitors were in
* an inconsistent state, the damaged objects become visible to
* other threads, potentially resulting in arbitrary behavior. Many
* uses of stop should be replaced by code that simply
* modifies some variable to indicate that the target thread should
* stop running. The target thread should check this variable
* regularly, and return from its run method in an orderly fashion
* if the variable indicates that it is to stop running. If the
* target thread waits for long periods (on a condition variable,
* for example), the interrupt method should be used to
* interrupt the wait.
*/
@Deprecated
public final void stop()

从官方解释中可可以看到这个方法已经被弃用,首先他会突然释放它多有的锁,这样就会导致前后不一致(inconsistent).他们也推荐使用中断标志来结束。

//共享数据
public class ShareData extends Thread{
	 String username = "a";
	 String password = "aa";
	
	public void print(String username,String password){
	     	this.username = username;
	     	Thread.sleep(2000);
	     	this.password = password;
	}
}

//一个简单的线程
public class A extends Thread{

	private ShareData  shareData;
	public A(ShareData  shareData){
		this.shareData = shareData;
	}
 

	@Override
	public void run() {
         shareData.print("b","bb");
   }
}

//主线程
 public static void main(String[] args) {
        try {
        	ShareData shareData = new ShareData();
            A thread = new A(shareData );
            thread .start();
            Thread.sleep(1000);

            thread stop();

			sout(shareData);//此时会打印b,aa(数据已经出现不一致了)

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

三、线程暂停

suspend和resumed,注意这两个方法也已经丢弃,但是了解丢弃的意义还是很有用的。

/**
* Suspends this thread.
* If the thread is alive, it is suspended and makes no further
* progress unless and until it is resumed.
* @deprecated This method has been deprecated, as it is
* inherently deadlock-prone. If the target thread holds a lock on the
* monitor protecting a critical system resource when it is suspended, no
* thread can access this resource until the target thread is resumed. If
* the thread that would resume the target thread attempts to lock this
* monitor prior to calling resume, deadlock results. Such
* deadlocks typically manifest themselves as “frozen” processes.
*/
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}

我认为官方这个解释已经够完美,书中说缺点–不同步其实基本不会出现。
inherently deadlock:天然的死锁情况
主要原因还是他不会释放它拥有的锁,比如执行suspend需要锁A,执行该方法后,他会一直暂停,指导调用resumed方法,如果调用resumed方法也需要锁A,那么就会无限死锁。

四、线程优先级

其实这个在大学学习操作系统的时候,讲的很清楚。
**优先级具有随机性:**线程的优先级也有规则性,那就是CPU尽量将执行资源让给优先级高的线程。这个尽量就体现了随机性。

四、守护线程

以前对守护线程理解有误。
守护线程其实就是个辅助角色,如果被辅助的不存在了,那么它就会消失。

 public static void main(String[] args) {
        try {
            A a  = new A();

            A aa  = new A();


            a.setDaemon(true);
            a.start();

            Thread.sleep(4000);

            System.out.println("main end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    private static class A extends Thread{

        int i;

        @Override
        public void run() {
            super.run();


            while(true){
                i++;
                System.out.println("i="+i);
            }
        }
    }

因为a是守护线程,所以随着主线程main结束,他也就结束了。

猜你喜欢

转载自blog.csdn.net/chuxue1989/article/details/88081942