java 线程的一些理解

程序:是一段静态的代码
进程:是程序的一次动态执行,对应代码的加载、运行和结束。进程有自己的专用内存区域
线程:比进程的单位小,没有自己的内存区域,多个线程之间可以共享对应进程的内存区域(包括代码和数据),并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。

每个java程序都有一个主线程。jvm发现main方法就开始执行,当主线程及所有子线程都结束时,程序结束。每个线程对应一个任务,多任务对应为多线程。

调度方式:抢占式调度和协作式调度。
抢占式调度:直接中断而不需要和被中断程序协商
协作式调度:中断时需要协商
目前大部分操作系统都采用抢占式调度,小型设备,如手机,则采用协作式调度。

线程的状态及对应的java代码:
1、新建:
     当一个thread类或其子类对象呗声明并创建,那么线程对象就处于新建状态,此时该线程已经拥有了相应的内存空间及其他的资源
2、运行:
     当调用start方法时,线程开始运行,并执行run中的方法。在run中,不应该再调用start方法,否则会发生异常
3、阻塞:
     阻塞的原因有:
     1、线程试图获得一个锁,但该锁正在被别的线程占用。
     2、当前线程执行了sleep方法或者wait方法,则线程挂起。若执行wait方法,则需要等待其他线程执行notify方法或者notifyall方法来唤醒他,之后该线程进入队列等待CPU资源。若执行sleep方法,则当sleep时间过了,该线程就可以进入队列等待CPU资源。
     3、线程执行过程中,某个方法发生了阻塞,则线程挂起。当阻塞原因消除,那么线程进入线程队列等待CPU资源
     4、线程等待一个触发条件,而该条件还没发生。
4、死亡:
     线程执行完run方法
     因为一个未捕获的异常而导致线程终止

注:当线程从阻塞状态恢复过来时,判断该线程与当前正在运行的线程的优先级,若该线程优先级比较高,则直接抢占CPU资源

线程的状态转换图如下所示:

优先级及调度顺序:
jvm线程调度器负责管理线程,线程的优先级分为1~10,主要使用的是1,5,10,尤其有些操作系统只识别这三种优先级。高的优先级的线程先运行,同等优先级的线程以轮流方式使用时间片。只有当高级别的线程死亡时,或者使用sleep方法或者wait方法挂起时,低级别的线程才能获得CPU资源。

守护线程:
这样的线程往往是为别的线程提供服务,在线程运行前设置。当程序只剩下守护线程时,程序退出

java中实现线程的方法:
1、继承Thread类,并重写run方法
2、实现runnable接口。
第二个方法更好,因为java不支持多继承,Thread子类不能再扩展其他的类。另外,使用runnable可以实现多线程间的资源共享。

以卖票为例:
若用Thread子类方法:
public MyThread extends Thread{
       private int ticket = 10;
       public void run(){
for(int i=0;i<20;i++){  
if(this.ticket>0){  
System.out.println("卖票:ticket"+this.ticket--);  
}  
}
};
public class ThreadTicket{
    public static void main(String[] args)
    {
          MyThread mt1 = new MyThread();
          MyThread mt2 = new MyThread();
          MyThread mt3 = new MyThread();
          mt1.start();
          mt2.start();                               
          mt3.start();
          //运行结果,三个线程,每个线程卖了10张票,一共卖了30张票
}

使用runnable方法:
package  org.demo.runnable;  
class  MyThread  implements  Runnable{  
private   int  ticket= 10 ;  
public   void  run(){  
for ( int  i= 0 ;i< 20 ;i++){ 
if ( this .ticket> 0 ){ 
System.out.println( "卖票:ticket" + this .ticket--); 
}  
}  
} ; 
package  org.demo.runnable;  
public   class  RunnableTicket {  
public   static   void  main(String[] args) {  
MyThread mt= new  MyThread();  
        new  Thread(mt).start(); //同一个mt,然而在Thread中就不可以,假如用同一   
new  Thread(mt).start(); //个实例化对象mt,就会浮现 异样   
new  Thread(mt).start();  
//三个线程一共卖了10张票,因为都用了同一个runnable对象
}  
}; 
//这里线程中run方法的步骤较少,因此可能不会出现同步错误。但是应该用synchronized关键字,或者ReentrantLock方法来保证同步。

线程的同步:
重点保证在每个时刻只能有一个线程能够进入临界区域。尽量用synchronized方法,这样可以减少代码量,也可以减少因为忘记写signal方法二引发错误。
JDK5.0之前通过synchronized方法或者synchronized块来实现,使用了这个关键字的方法或块每次只能被一个线程使用。
JDK5.0之后通过ReentrantLock来实现:
myLock.lock();
try{
....
}
finally{
mylock.unlock(); }

对域的安全访问:加violate关键字:

条件对象,或称条件变量:
在银行算法中,如果某个需要转出的账户中余额不足,则需要等待某个账户向该账户中存储钱才能继续转账操作。
Bank类构造函数:

转账函数:

//当余额不足时,用await方法阻塞。同时如果其他线程完成了转账过程,则唤醒因为余额不足而阻塞的线程。在当前线程完成了同步操作后,被唤醒的线程将进入竞争状态。

同样的功能,使用synchronized方法的代码如下:

死锁:
当所有的线程都阻塞了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值