黑马程序员_多线程

—————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————

线程是一个程序里不同的执行路径



多线程创建的两种方法:

1、继承Thread类。

①定义类继承Thread。

②复写Thread类中的run方法。

③调用线程的start方法,该方法有两个作用:启动线程,调用run方法。


发现运行结果每一次都不同,

因为多个线程都获取cpu的执行使用权,cpu执行到谁,谁就运行。

在某一个时刻,只能有一个程序在运行。(多核除外)

cpu在做着快速切换,以达到看上去同时运行的效果。

我们可以形象的把多线程的运行行为在互相抢夺cpu的执行权。

这就是多线程的特性,随机性。谁抢到谁执行,至于执行多长时间,cpu说的算。


2、通过实现Runnable接口线程创建

(1).定义一个类实现Runnable接口,重写接口中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。

(2).创建Runnable接口实现类的对象。

(3).创建一个Thread类的对象,需要封装前面Runnable接口实现类的对象。(接口可以实现多继承)

(4).调用Thread对象的start()方法,启动线程


采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。



class Speak extends Thread{
	public void run(){
		for(int i=0;i<80;i++){
			System.out.println("speak="+i);
		}
	}
}


public class testthread{
	public static void main(String[] args){
		Speak s = new Speak();
		Write w = new Write();
		s.start();
		new Thread(w).run() ;
		for(int i=0;i<80;i++){
			System.out.println("main="+i);
		}
	}
}

class Write implements Runnable{
	public void run(){
		for(int i=0;i<80;i++){
			System.out.println("write="+i);
		}
	}
}





class Speak extends Thread{
	public int nub;
	public void run(){
		for(nub=0;nub<80;nub++){
			System.out.println("speak="+nub);
			yield();
			//暂停当前正在执行的线程对象,并执行其他线程。 
		}
	}
}


public class TestThread{
	public static void main(String[] args) throws Exception{
		Speak s = new Speak();
		Write w = new Write();
		s.start();
		new Thread(w).run() ;
		s.join();
		System.out.println("Thread(Speack)="+s.nub);
		for(int i=0;i<10;i++){
			System.out.println("main="+i);
		}
	}
}

class Write implements Runnable{
	public void run(){
		for(int i=0;i<80;i++){
			System.out.println("write="+i);
		}
	}
}


由上可知道join方法的用法:主线程生成并起动了子线程,而子线程里要进行大量的耗时的运算(这里可以借鉴下线程的作用),当主线程处理完其他的事务后,需要用到子线程的处理结果,这个时候就要用到join();方法了。



锁的机制:synchronized(互斥锁)

Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

 一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

 二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

 三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。 

 四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。 

 五、以上规则对其它对象锁同样适用.Java线程死锁是一个经典的多线程问题,因为不同的线程都在等待那些根本不可能被释放的锁,从而导致所有的工作都无法完成。


关于 多线程死锁

Java线程死锁是一个经典的多线程问题,因为不同的线程都在等待那些根本不可能被释放的锁,从而导致所有的工作都无法完成

经典问题,wiki百科哲学家吃饭问题

简单解决办法是将锁加粗。

class Ticket implements Runnable{
  private  int tick = 1000;
  Object obj = new Object();
  boolean flag = true;
  public  void run(){
    if(flag){
      while(true){
        synchronized(obj){
           show();
        }
      }
    }
    else
    while(true)
    show();
  }
  public synchronized void show()//this{
    synchronized(obj){
      if(tick>0){
        try{Thread.sleep(10);}catch(Exception e){}
        System.out.println(Thread.currentThread().getName()+"....code : "+ tick——);
      }
    }
  }
}
class  DeadLock{
  public static void main(String[] args) {
    Ticket t = new Ticket();
    Thread t1 = new Thread(t);
    Thread t2 = new Thread(t);
    t1.start();
    try{Thread.sleep(10);}catch(Exception e){}
    t.flag = false;
    t2.start();
  }
}


—————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马程序员多线程练习题主要包括两个问题。第一个问题是如何控制四个线程在打印log之前能够同时开始等待1秒钟。一种解决思路是在线程的run方法中调用parseLog方法,并使用Thread.sleep方法让线程等待1秒钟。另一种解决思路是使用线程池,将线程数量固定为4个,并将每个调用parseLog方法的语句封装为一个Runnable对象,然后提交到线程池中。这样可以实现一秒钟打印4行日志,4秒钟打印16条日志的需求。 第二个问题是如何修改代码,使得几个线程调用TestDo.doSome(key, value)方法时,如果传递进去的key相等(equals比较为true),则这几个线程应互斥排队输出结果。一种解决方法是使用synchronized关键字来实现线程的互斥排队输出。通过给TestDo.doSome方法添加synchronized关键字,可以确保同一时间只有一个线程能够执行该方法,从而实现线程的互斥输出。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [黑马程序员——多线程10:多线程相关练习](https://blog.csdn.net/axr1985lazy/article/details/48186039)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值