天天看点

黑马程序员 Java多线程

------- android培训、java培训、期待与您交流! ----------

1,可以使用静态方法Thread.currentTread().getName()来获取当前线程的线程名

2,如果我们对某个线程对象在启动之前调用了setDaemon(true)方法,这个线程就变成了后台线程,对JAVA程序来说,只要还有一个前台线程在运行,这个进程就不会结束,如果一个进程中只有后台线程运行,这个进程就会结束,setDaemon方法首先调用该线程的checkAccess方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)如果指示线程没有处于请求操作所要求的适当状态还会抛出IllegalThreadStateException异常

注:

checkAccess public final void checkAccess()判定当前运行的线程是否有权修改该线程。如果有安全管理器,则调用其 checkAccess方法,并将该线程作为其参数。这可能导致抛出 SecurityException -如果不允许当前线程访问该线程

3,线程A调用线程B的join()方法后,线程A就会等线程B结束后才继续运行,join()等待该线程终止,join(long millis)等待该线程终止的时间最长为 millis毫秒。join(long millis,int nanos)等待该线程终止的时间最长为 millis毫秒 + nanos 纳秒。

注:

join

public final void join(long millis,  int nanos) throwsInterruptedException等待该线程终止的时间最长为 millis毫秒 + nanos 纳秒。

参数:

millis - 以毫秒为单位的等待时间。

nanos - 要等待的 0-999999附加纳秒。 

抛出: 

IllegalArgumentException - 如果 millis值为负,则 nanos的值不在 0-999999范围内。 

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态被清除。

public final void join()  throwsInterruptedException等待该线程终止。

抛出: 

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态被清除。

public final void join(long millis) throws InterruptedException等待该线程终止的时间最长为 millis毫秒。超时为 0 意味着要一直等下去。

参数:

millis - 以毫秒为单位的等待时间。 

抛出: 

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态被清除。

4,创建多线程有两种方式,一种是继承Thread类,另一种是实现Runnable接口,我觉得如果能使用接口就选择接口,因为这确实能很好地体现出面向对象的设计思想

5,sleep

public static void sleep(long millis) throws InterruptedException在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。

参数:

millis - 以毫秒为单位的休眠时间。 

抛出: 

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态被清除。

6,当在线程A中启动了线程B后,CPU不一定立刻跳转到线程B,它很可能要再在线程A中执行一会儿了再跳转到线程B,为了让CPU立刻跳转到线程B,我们可以在启到了线程B后在线程A中调用Tread类中的sleep方法让线程A等待一会儿

7,synchronized的四种用法:

(1)方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前,即一次只能有一个线程进入该方法,其他线程想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入。

(2)对某一代码块使用,synchronized后跟括号,括号里是变量,这样一次只有一个线程进入该代码块。

(3)synchronized后面括号里是一对象,如果线程进入,则得到对象锁,那么别的线程在该类所有对象上的任何操作都不能进行。在对象级使用锁通常是一种比较粗糙的方法。为什么要将整个对象都上锁,而不允许其他线程短暂地使用对象中其他同步方法来访问共享资源?如果一个对象拥有多个资源,就不需要只为了让一个线程使用其中一部分资源,就将所有线程都锁在外面。由于每个对象都有锁,所以可以使用虚拟对象来上锁.

  (4)synchronized后面括号里是类,如果线程进入,则线程在该类中所有操作不能进行,包括静态变量和静态方法,实际上,对于含有静态方法和静态变量的代码块的同步,我们通常用4来加锁

以上4种之间的关系:

锁是和对象相关联的,每个对象有一把锁,为了执行synchronized语句,线程必须能够获得synchronized语句中表达式指定的对象锁,一个对象只有一把锁,被一个线程获得之后它就不再拥有这把锁,线程在执行完synchronized语句后,将获得锁交还给对象。在方法前面加上synchronized修饰符即可以将一个方法声明为同步化方法。同步化方法在执行之前获得一个锁。如果这是一个类方法,那么获得的锁是和声明方法的类相关的Class类对象的锁,如果这个一个实例方法,那么此锁是this对象的锁。

8,public final void wait(long timeout) throwsInterruptedException

参数:

timeout - 要等待的最长时间(以毫秒为单位)。 

抛出: 

IllegalArgumentException - 如果超时值为负。 

IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。 

InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的中断状态被清除。

public final void wait(long timeout, int nanos) throwsInterruptedException

参数:

timeout - 要等待的最长时间(以毫秒为单位)。

nanos - 额外时间(以毫微秒为单位,范围是 0-999999)。 

抛出: 

IllegalArgumentException - 如果超时值是负数,或者毫微秒值不在 0-999999范围内。 

IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。 

InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的中断状态被清除。

public final void wait()(等价于wait(0))throws InterruptedException

抛出: 

IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。 

InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的中断状态被清除。

9,public final void notify()唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。

直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。

此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者:

通过执行此对象的同步实例方法。 

通过执行在此对象上进行同步的 synchronized语句的正文。 

对于 Class 类型的对象,可以通过执行该类的同步静态方法。 

一次只能有一个线程拥有对象的监视器。 

抛出: 

IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。

10,public final void notifyAll()唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait方法,在对象的监视器上等待。

直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。

此方法只应由作为此对象监视器的所有者的线程来调用。有关线程能够成为监视器所有者的方法的描述,请参阅 notify方法。 

抛出: 

IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。

11,练习题:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次,请写出程序

这道题我和张老师做得不一样,他是把主线程循环的100次和和子线程循环10次写成两个方法的,而我是写成一个方法通过传递所需循环的次数的参数来实现的

1.    public class ThreadTest {  

2.        public static void main(String[] args) {  

3.            final ThreadCommunication threadCommunication = new ThreadCommunication();  

4.            new Thread(new Runnable() {  

5.                @Override  

6.                public void run() {  

7.                    for (int i = 1; i <= 50; i++) {  

8.                        threadCommunication.print(10);  

9.                    }  

10.              }  

11.          }).start();  

12.          for (int i = 1; i <= 50; i++) {  

13.              threadCommunication.print(100);  

14.          }  

15.      }  

16.  }  

17.    

18.  class ThreadCommunication {  

19.      private int temp;  

20.      private boolean flag = true;  

21.    

22.      public synchronized void print(int num) {  

23.          while (!flag & 10 == num || flag & 100 == num) {  

24.              try {  

25.                  this.wait();  

26.              } catch (InterruptedException e) {  

27.                  e.printStackTrace();  

28.              }  

29.          }  

30.          for (temp = num; temp > 0; temp--) {  

31.              System.out.println(Thread.currentThread().getName() + temp);  

32.          }  

33.    

34.          flag = false == flag ? true : false;  

35.          this.notify();  

36.      }  

37.  }  

12,张老师在视频中提到了捕获线程死亡事件,这个在课堂上没有找到方法,我就好奇的也试着看了看API,这是我个人的捕获线程死亡事件做法,也不知道是不是这么一回事

1.    public class CatchThreadTerminate {  

2.        public static void main(String[] args) {  

3.            final Thread thread = new Thread(new Runnable() {  

4.                @Override  

5.                public void run() {  

6.                    for (int i = 0; i <= 100; i++) {  

7.                        System.out.println(i);  

8.                    }  

9.                }  

10.          });  

11.          thread.start();// 启动thread线程  

12.          new Thread(new Runnable() {  

13.    

14.              @Override  

15.              public void run() {  

16.                  while (true) {  

17.                      if (Thread.State.TERMINATED == thread.getState()) {  

18.                            

19.                          System.out.println("线程死亡");  

20.                          break;// 已经捕获到thread的死亡,结束监听  

21.                      }  

22.                  }  

23.              }  

24.    

25.          }).start();// 启动一个线程来监听thread线程是否是亡  

26.      }  

27.  }