黑马程序员——多线程学习笔记日志

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

多线程学习笔记日志
1.线程的描述,任何一个程序都是由进程去运行的,而进程的原理是进程内部封装了许多的线程,这些线程就可以去执行相对应的具体功能了,而多线程的出现就提高了程序运行的效率,拿电脑来说,若电脑中有一个cpu,cpu要执行这些程序必须在这些线程进行快速的切换,且在某一瞬间只能执行一个线程,有了多线程后则可以同时运行多个程序了。
2.如何创建线程,线程在java语言中有一个类描述即Thread,Thread类中有多个构造函数,创建线程有2中方法,一种是继承Thread类,另一种是继承Runnable接口,先说第一种,继承Thread类,见以下代码:
class Pan extends Thread 
{
 Pan(String name)
 {
  super(name); 这里若不写构造函数,则线程用的是默认的名字。注意,继承Thread类给线程自定义名字时,必须调用父类Thread中的构造函数将参数传递给父类,否则名字自定义不了。
 }
 public void run()
 {
  for (int x=0;x<100 ;x++ )
  {
   System.out.println(Thread.currentThread().getName()+"....."+x);
  }
 }
}
若想获取线程名称,可以通过Thread类名调用该类中的静态方法currentThread()方法,获取到了当前正在执行的线程对象的引用,即一个线程对象,然后在通过getName()方法获取线程名称,或者通过this.getName()方法获取。
还可以通过setName()来修改线程名称。
在主函数中建立该类的对象,即可创建一个线程了,然后通过start()方法启动该线程,线程运行的内容即为run()方法中的内容。
第二种方法是通过一个类实现Runnable接口来建立的,具体如下:
class Demo implements Runnable
{
 public void run() 
 {
  for (int x=0;x<100 ;x++ )
  {
   System.out.println(Thread.currentThread().getName()+"....."+x);获取线程名称,同理也是通过该方法来获取线程名称。
  }
 }
}
实现了该Runnable接口后,建立该类的对象,Demo d=new Demo();
将该对象作为参数传递给线程对象,Thread t=new Thread(d,"自定义线程名字");该方法给线程自定义名称时直接在Thread类的构造函数中传入参数即可。
在实际应用中最好用实现Runnable接口的方法,因为java中支持单继承,多实现,这样可以有利于功能的扩展。

创建线程的另外一种方式,通过匿名内部类的方式来创建线程,如下:

new Thread(new Runnable(){
   public void run()
   {
    for(int y=0;y<10;y++)
    {   
     System.out.println(Thread.currentThread().getName()+y);
    }
   }
  },"线程名称").start();

这种方式比较简化,具体用哪种方式创建线程主要看需求。
3.当多个线程在对共享数据进行同时操作时,有可能会出现安全隐患,比如多线程买票例子,如下:
比如tick的初始值为200,且是静态的,当有2个线程同时在操作数据时,就会出现安全问题,
static int tick=200;
while(true)
{
    if(tick>0)    若此时tick值为1了,而A与B线程都满足了条件,若A进入了 循环,此时B抢到了执行权,B线程执行了程序将tick的值等 于1打印了,将tick变为了0,A下来后就将tick=0打印出去了,就出了问题。
    -->A
    -->B
    System.out.println(tick--);
}
4.如何解决安全问题呢,可以使用同步的方法,给共享的代码加一把锁,同步的前提是有多个线程存在,且多个线程在操作同一共享数据,
synchronized(对象) 
{
    需要被同步的代码
}
该对象可以是任意的,对象就好比一把锁,有锁的线程就可以执行函数中的代码。但每次都要判断锁,消耗资源。
5.同步函数:所谓同步函数就是将整个函数进行同步,只需要在函数上加关键字synchronized修饰即可,同步函数使用的锁是this,静态同步函数使用的锁是该类名.class,若想要多个线程执行不同函数中的代码时,且也要操作共享数据,则可以让这些要同步运行的代码用同一把锁。
6.死锁:所谓死锁就是A锁中的函数有B锁,而B锁中的函数也有A锁,A向B要锁,B向A要锁,因此互相僵持不下。
自己写的死锁程序,将比老师的代码做了些修改,毕老师是将2个同步代码放在了一个函数中,为了体现出我的不同之处,我将2个代码分别放在了2个不同的函数中,哈哈^_^o(∩_∩)o...哈哈进步了
class ThreadDemo
{
 public static void main(String[] args)
 { 
   new Thread(new Demo1()).start();
   new Thread(new Demo2()).start();  
 }
}
class MyLock
{
 static MyLock locka=new MyLock();
 static MyLock lockb=new MyLock();
}
class Demo1 implements Runnable
{
 public void run()
 {
   synchronized(MyLock.locka)
   {
      System.out.println("if lock aa");
    synchronized(MyLock.lockb)
    {
     System.out.println("if lock bb");
    }
   }    
 }
}
class Demo2 implements Runnable
{
 public void run()
 {  
   synchronized(MyLock.lockb)
   {
      System.out.println("else lock bb");
    synchronized(MyLock.locka)
    {
     System.out.println("else lock aa");
    }
   }  
 }
}
7:总结,熟悉Thread类中的一些其他方法,比如join(),yeild()等,多看API文档即可,多线程中关于等待唤醒机制这里会比较复杂,同步函数跟同步代码块也很重要,判断什么时候要用同步函数或者同步代码块,需要弄清楚哪些数据是共享数据,哪些数据在被多个线程同时操作,如果有则需要用到同步,如果没有则最好别用同步,因为同步会使程序运行效率降低,还必须要注意的是同步函数同步函数用的锁必须是同一把锁,只有弄清楚了同步函数的原理,才能避免死锁的发生。

关于创建线程的方法,还有一个非常重要的内容,就是通过另外一个类Executors来创建线程,而且功能比普通的线程要强大,可以创建线程池,创建一个线程定时器,非常的有用,特别是线程定时器,可以控制程序运行的节奏,很多地方都用得到。

------- android培训java培训、期待与您交流! ----------  详细请查看:http://edu.csdn.net/heima/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值