java无难事笔记(七)

Java虚拟机启动的时候就会有一个非后台线程去执行main方法!

 

java.lang
类 Thread

java.lang.Object

  java.lang.Thread

所有已实现的接口:

Runnable


public class Thread

extends Object

implements Runnable

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。

每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。

当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:

  • 调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作发生。
  • 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。

创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成:


     class PrimeThread extends Thread {

         long minPrime;

         PrimeThread(long minPrime) {

             this.minPrime = minPrime;

         }

 

         public void run() {

             // compute primes larger than minPrime

              . . .

         }

     }

 


然后,下列代码会创建并启动一个线程:

     PrimeThread p = new PrimeThread(143);

     p.start();

 

创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:


     class PrimeRun implements Runnable {

         long minPrime;

         PrimeRun(long minPrime) {

             this.minPrime = minPrime;

         }

 

         public void run() {

             // compute primes larger than minPrime

              . . .

         }

     }

 


然后,下列代码会创建并启动一个线程:

     PrimeRun p = new PrimeRun(143);

     new Thread(p).start();

 

每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。

 

Thread.getName()返回线程的名字!

 

 

Thread.setDemaon()方法用来设置将一个线程设置为后台线程!

将一个线程设置为后台线程,必须在这个线程调用start()方法之前,

如果所有线程都是后台线程,那么java虚拟机将退出!

 

 

Yiled方法可以是当前线程放弃执行权力!

 

线程优先级范围是110 10为最高

Thread定义了三个常量!

 

调用yiled方法的时候,将这个线程进入等待状态,如果一个具有高优先级线程,搞优先级线程将会一直占据CPU

Java不支持时间片轮转,它只是支持高优先调用

 

 

第二种方法是实现Runable接口,

将实现了Runable接口的类的一个实例作为Thread构造函数的参数

然后再调用start()方法!

 

获取当前线程的名字Thread.currentThread获取当前线程的实例!

 

两种方法选择

实现Runable接口,一方面可以避免多重继承的情况,java不支持,另外一方面也可以方便实现共享变量!可以实现贡献变量

 

不过共享变量可以通过内部类来是实现,内部类实现Runable接口,提供run方法

在通过一个方法向外面提供Thread对象!

 

同步的两种方式:同步块和同步方法

每一个对象都有一个监视器,或者叫做锁。

同步方法利用的是this所代表的对象的锁。

每个class也有一个锁,是这个class所对应的Class对象的锁。

 

 

同步块:

 

Object o = new Object()

Synchronized(o)//进入的时候会把对象O的锁给关上,大括号出来的时候把锁给打开

{
}

 

这个同步块会出现问题

 

int tickets = 100;

         Object o = new Object();

         public void run()

         {

                   while(tickets>0)

                   {

                            synchronized(o)

                            {

                                     try

                                     {

                                               Thread.sleep(10);

                              }

                              catch(Exception e)

                              {

                                   e.printStackTrace();

                              }

                             System.out.println(Thread.currentThread().getName()+" sell ticket:"+tickets);

                             tickets--;

                            }

                   }

 

当最后一张票的时候tickets=1tickets,三个线程都一样,在进入关键区之前都会进行判断tickets是否大于1,结果都是true,所以进入关键代码段,但是一个时候只能有一个线程执行,其余线程就等待,这个线程执行完之后tickets=0,这个时候第二个线程获得进入关键代码段权力,再买一张tickets-1,第三个线程就买-2票了,这个例子告诉我们,要把共享变量保护起来而不仅仅是在修改的时候,判断时候也要保护起来

 

 

 

同步方法:

 

class SellThread implements Runnable

{

         int tickets = 100;

         Object o = new Object();

         public void run()

         {

                   while(true)

                   {

                            sell();

                   }

         }

         public synchronized void sell()

         {

                                     if(tickets>0)

                                     {

                                               try

                                               {

                                                        Thread.sleep(10);

                                       }

                                       catch(Exception e)

                                       {

                                            e.printStackTrace();

                                       }

                                      System.out.println(Thread.currentThread().getName()+" sell ticket:"+tickets);

                                      tickets--;

                                     }

         }

         }

 

采用同步方法,写一个方法synchronized,然后再run里面调用这个函数!也可以实现同步!

同步方法是对 this对象进行加锁,返回的时候对this监视器进行解锁!

 

线程调用start()之后并不会立即启动,主要是因为调用start的主线程时间片没有结束!

 

Wait()notify()

必须在一个同步块或者同步方法中调用!

waitnotify要在同一个对象的等待队列删除,添加线程!

 

yiled线程调用一个可运行的状态,当前运行线程变为一个可运行的线程Runnable状态!

 

 

 

Stop会解锁所有线程的监视器,会导致线程状态不一致

已经停用

Suspendresume已经停用

如果要终止一个线程可以调用

1,  设置一个变量boolrsm

Run方法

{

While(!bStop)

{

…….
}

Void syop()

{

Bstop=false;
}
}

 

Thread.Interrupt(),那么wait方法会抛出InterruptedException e异常

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值