`
accpxudajian
  • 浏览: 456474 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

线程2

    博客分类:
  • Java
阅读更多

>>3内部class类继承Thread的线程实现方式
public class TestThread
{
public static void main(String[] args)
{
  //实现Runnable接口得线程实现方式 用与和内部类比较
  MyThread myt1 = new MyThread();
  //new Thread(myt).start()的理解:根据myt对象,实例化一个线程对象,并开始线程
  new Thread(myt1).start();
//内部类继承Thread类的线程实现方式
  MyThread2 myt = new MyThread2();
  //由于内部类继承Thread类,所以可以使用start方法,但是方式很特别
  myt.new InnerThread().getThread().start();
  System.out.println("main方法线程名字:"+Thread.currentThread().getName());
}
}
//实现Runnable接口的 实现线程的方法
class MyThread implements Runnable
{
public void run()
{
  System.out.println("实现Runnable接口子线程得名字:"+Thread.currentThread().getName());
}
}
//内部类继承Thread类  实现线程 赞成频繁使用
class MyThread2
{
//定义内部类:1内部类继承Thread类或实现Runnable接口,覆盖run方法  2提供一个返回值是Thread的方法,返回内部类的对象 class InnerThread extends Thread
{
  public void run()
  {
    System.out.println("内部类输出线程名称:"+Thread.currentThread().getName());
  }
}
//返回值为线程类型的方法 实例化并返回内部类 (内部类实现线程的关键)Thread getThread()
public Thread getThread
{
  return new InnerThread();
}
}
>>4线程同步(synchronized)得实现:同步块和同步方法
public class TestThread
{
public static void main(String[] args)
{
  //四个线程同时销售100张票
  //同步块实现售票
  //SellThread myt = new SellThread();
  //new Thread(myt).start();//开启第一个窗口开始售票 即开启一个线程对同步对象惊醒操作 实现了共享数据同步操作
  //new Thread(myt).start();//开启第二个窗口开始售票 即开启一个线程对同步对象惊醒操作
  //new Thread(myt).start();//开启第三个窗口开始售票 即开启一个线程对同步对象惊醒操作
  //new Thread(myt).start();//开启第四个窗口开始售票 即开启一个线程对同步对象惊醒操作

//同步方法实现售票
  SellThread1 myt1 = new SellThread1();
  new Thread(myt1).start();//开启第一个窗口开始售票
  new Thread(myt1).start();//开启第二个窗口开始售票
  new Thread(myt1).start();//开启第三个窗口开始售票
  new Thread(myt1).start();//开启第四个窗口开始售票

}
}
//同步块 对某一个对象Ojbect进行加锁
class SellThread implements Runnable
{
int tickets= 100;//100张票
Object obj =  new Object();//同步变量
public void run()
{
  while(true)
  {
//给obj对象加锁,直到同步块结束,“{”表示给obj对象加锁,"}"表示给obj对象解锁
   synchronized(obj)  
{
    if(tickets>0)
    {
//sleep是Thread类的静态方法,调用时会抛出异常,需要捕获
     try{
      Thread.sleep(10);
     }catch(Exception e)
     {
      e.printStackTrace();
     }
     System.out.println("线程:"+Thread.currentThread().getName()+"sell==="+tickets);
     tickets--;
    }
   }
/*错误的方法:先锁住对象,在while循环,最终只走一个线程(与上边对比:先while再synchronized)
//同步块
synchronized(this)
{
while(tickets>0)    
   {
    try{
     Thread.sleep(1000);
    }
    catch(Exception e)
    {
     e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+"sells tickets==="+tickets);
    tickets--;
   }
  }
*/
  }
}
}

//同步方法 对this加锁
class  SellThread1 implements Runnable
{
int tickets= 100;//100张票
//run方法调用同步方法sell
public void run()
{
  sell();
}
//声明同步方法的关键字:synchronized
public synchronized void sell()
{
  while(true)
  {
    if(tickets>0)
    {
     try{
      Thread.sleep(10);
     }catch(Exception e)
     {
      e.printStackTrace();
     }
     System.out.println("线程:"+Thread.currentThread().getName()+"sell==="+tickets);
     tickets--;
    }
  }
}
}

>>5 同步块和同步方法实现共享数据的同步
public class TestThread
{
public static void main(String[] args)
{  
//同步块和同步方法实现共享数据的同步(特点:同步块的同步对象为this,如果同步对象是obj,则会出现index=0)
  SellThread myt1 = new SellThread();  
  new Thread(myt1).start();//开启第一个窗口开始售票 启动第一个线程
  try{
   Thread.sleep(1);//主线程休眠
  }
  catch(Exception e)
  {
   e.printStackTrace();//sleep方法会抛出异常,所以需要捕获
  }
  myt1.bFlag = true;//改变bFlag得值为true
  new Thread(myt1).start();//开启第二个窗口开始售票

}
}
//对某一个Object对象进行加锁
class SellThread implements Runnable
{
int tickets= 100;//100张票
Object obj =  new Object();//同步变量
boolean bFlag = false;//同步方法和同步块转换的条件
public void run()
{  
   if(bFlag==false)
   {
    while(true)
     sell();
   }else    {
    while(true)
    {
     //同步块
synchronized(this)
     {
      if(tickets>0)
      {
       try{
         Thread.sleep(10);
        }
        catch(Exception e){
         e.printStackTrace();
        }
       System.out.println("同步块线程:"+Thread.currentThread().getName()+"sell==="+tickets);
       tickets--;
      }
     }
    }
   }
  
}

//同步方法
public synchronized void sell()
{
  if(tickets>0)
  {
   try{
    Thread.sleep(10);
   }
   catch(Exception e){
    e.printStackTrace();
   }
   System.out.println("同步方法线程:"+Thread.currentThread().getName()+"sell==="+tickets);
   tickets--;
  }
}
}


>>6线程同步时发生的死锁
线程A和B,A的同步对象m,n,B的同步也是对象m,n,进程A运行时先锁住m,进程B运行时先锁住n,A进程要用到n对象能完成但是n已经被B锁住,所以进程A进入等待状态,B进程要用到m对象才能完成但是m对象已经被A锁住,所以进程B也进入等待状态,出现死锁。
《红色标记为出现死锁得代码,注意与上例的比较》
public class TestThread
{
public static void main(String[] args)
{  
  SellThread myt1 = new SellThread();  
  new Thread(myt1).start();//开启第一个窗口开始售票
  try{
   Thread.sleep(1);//主线程休眠
  }
  catch(Exception e)
  {
   e.printStackTrace();//sleep方法会抛出异常,所以需要捕获
  }
  myt1.bFlag = true;//改变b得值为true
  new Thread(myt1).start();//开启第二个窗口开始售票
}
}
//对某一个对象进行加锁
class SellThread implements Runnable
{
int tickets= 100;//100张票
Object obj =  new Object();//同步变量
boolean bFlag = false;
public void run()
{
  
   if(bFlag==false)
   {
    while(true)
     sell();
   }else
   {
    while(true)
    {
    //同步块
synchronized(obj)
      {      
           try{
                     Thread.sleep(10);
            }
              catch(Exception e){
                    e.printStackTrace();
             }

                synchronized(this)
                 {
                      if(tickets>0)
                      {
                             System.out.println("同步块线程:"+Thread.currentThread().getName()+"sell==="+tickets);
                              tickets--;
                     }
            }
     }
    }
   }
  
}

//同步方法
public synchronized void sell()
{
  synchronized(obj)
  {
   if(tickets>0)
   {
    try{
     Thread.sleep(10);
    }
    catch(Exception e){
     e.printStackTrace();
    }
    System.out.println("同步方法线程:"+Thread.currentThread().getName()+"sell==="+tickets);
    tickets--;
   }
  }
  
}
}

>>7"生产者--消费者"模型 " 等待--通知(wait---notify)"模型。 一定是同步方法且作用同一个对象
public class TestThread
{
public static void main(String[] args)
{  
MyQueue q = new MyQueue();
//创建生产者
  Producer p = new Producer(q);
//创建消费者
  Consumer c = new Consumer(q);
//开始成产
  p.start();
//k开始消费
  c.start();
}
}
//树洞类 存放和取走数据
//存放和取走得方法都是同步的方法,且针对同一个变量value
class MyQueue
{
//数据变量value
int value =0;
//标记数据是否被取走得变量bFull
boolean bFull = false;
//消费者获得数据得方法
synchronized int  get()
{
  //如果不是满的,也就是没有数据,则等待生产者放入数据
  if(!bFull)
  {
   try
   {
    wait();
   }
   catch (Exception e)
   {
    e.printStackTrace();
   }
  }
  //改变是否取走数据得状态标记的值
  bFull = false;
  //通知生产者,放入数据
  notify();
  //返回数据,消费者取走数据
  return value;
}
//生产者放入数据的方法
synchronized void  set(int intValue)
{
  //如果数据不是满的,也就是数据被消费者取走了,则放入数据
  if(!bFull)
  {
   //生产者放入数据
   this.value = intValue;
   //改变数据是否被取走得标记
   bFull = true;
   //通知消费者来取数据
   notify();
  }
  //如果数据是满的,也就是消费者还没哟取数据,则等待消费折取走数据
  try{
   wait();
  }
  catch(Exception e){
   e.printStackTrace();
  }
}
}

//生产者类---情报员
class Producer extends Thread
{
MyQueue q;
Producer(MyQueue q)
{
  this.q = q;
}
public void run()
{
  for(int i=0;i<10;i++)
  {
   q.set(i);
   System.out.println("set==="+i);
  }
}
}

//消费者类 ---情报员
class Consumer extends Thread
{
MyQueue q;
Consumer(MyQueue q)
{
  this.q = q;
}
public void run()
{
  while(true)
  {
   System.out.println("get====="+q.get());
  }
}
}

>>7终止线程得方法:1变量控制
public class TestThread
{
public static void main(String[] args)
{
  Consumer c = new Consumer();
  c.start();
  int index =0;
  while(true){
   if(index++==500)
   {
   c.stopThread();//改变while循环的变量条件
    break;  //终止线程
   }
   System.out.println("main名字:"+Thread.currentThread().getName()+"index===="+index);
  }
  //程序结束输出
  System.out.println("main  exit()");
}
}
class Consumer extends Thread
{
//while循环的条件变量
private boolean bStop = false;

public void run()
{
  while(!bStop)
  {
   System.out.println("子线程名字:"+getName());
  }
}
//关闭线程的方法:改变while循环变量得条件
public void stopThread()
{
this.bStop  = true;
}
}

>>8带有wait方法的线程关闭方法2 :interrupt方法

public class TestThread
{
public static void main(String[] args)
{
  Consumer c = new Consumer();
  c.start();
  int index =0;
  while(true){
   if(index++==500)
   {
   c.stopThread();//改变while循环的变量条件 终止线程
    c.interrupt(); //关闭线程
    break;

   }
   System.out.println("main名字:"+Thread.currentThread().getName()+"index===="+index);
  }
  //程序结束输出
  System.out.println("main  exit()");
}
}
class Consumer extends Thread
{
//while循环的条件变量
private boolean bStop = false;
//wait方法一定要在静态方法或者静态块中
public synchronized void run()
{
  while(!bStop)
  {
   try{
    wait();//带有wait
   }
   catch(InterruptedException e)
   {
    //异常处理
    if(bStop){
     return ;
    }
   }
   System.out.println("子线程名字:"+getName());
  }
}
//关闭线程的方法:改变while循环变量得条件
public void stopThread()
{
  this.bStop  = true;
}
}

>>一个完整的内部类例子
//内部类实现
public class SellTicket
{
private  int tickets=100;
public SellTicket ()
{}
//内部类,继承Thread
class Sellor extends Thread
{
//重写run方法
  public void run()
  {
   synchronized(this)
   {
    while(tickets>0)
    {
    
     System.out.println(Thread.currentThread().getName()+"sells  tickets====="+tickets);
     tickets--;
    }
   }
  }
//方法返回值为Thread,返回内部类自己的实体对象(因为内部类已经继承了Thread或者实现了Runnable接口)
  public Thread getSellor()
  {
   return new Sellor();
  }

}
public static void main(String[] args)
{
  SellTicket sell = new SellTicket();
//调用内部类的线程并启动run方法
  sell.new Sellor().getSellor().start();
  
}
}
>>关于重写run方法的理解
一个类继承自Thread,此时可以不重写run方法,就等于使用Thread的run方法,run(){}方法是空的,所以没有意义但是不会出错;
一个类实现了 Runnable接口必须实现run方法,这是实现接口要求的,否则会出错

 

 

 

分享到:
评论

相关推荐

    C#泛型参数多线程与复杂参数多线程2

    最近用多线程用的比较多自己走了一些弯路,分享出来希望大家少走弯路,C#中的多线程有两个重载,一个是不带参数的,一个是带参数的,但是即便是带参数的多线程也不支持泛型,这使得使用泛型参数多线程的时候很不方便...

    多线程线程变量赋值

    // 输出线程2的值 }); thread1.start(); thread2.start(); // 主线程尝试获取值,此时值可能已经被子线程修改 System.out.println("Main Thread: " + threadVar.get()); } } ``` 在这个例子中,主线程设置...

    多线程2

    标题“多线程2”指的是在编程领域中关于多线程技术的深入探讨。多线程是计算机程序设计中的一项关键技术,特别是在并发处理和优化性能方面。它允许一个应用程序同时执行多个不同的任务,从而提高系统资源的利用率和...

    多线程编程-监控线程

    在上述示例中,作者创建了一个简单的多线程程序,其中包含两个被监控的线程(线程1和线程2)。为了确保线程的正确运行,程序使用了信号量进行同步控制,先启动线程1,再启动线程2。这是一个典型的生产者消费者模型,...

    多线程边改变边显示图像

    2. 创建处理线程:启动一个新的线程,该线程执行图像处理任务。处理过程中,线程会周期性地更新图像数据。 3. 获取锁:在更新图像数据前,处理线程需要先获得互斥锁,确保这段时间内没有其他线程访问图像数据。 4. ...

    使用多线程模拟火车站售票系统

    2. **条件变量(Condition Variable)**:条件变量允许线程等待某个特定条件满足后再继续执行。与互斥量配合使用,可以实现更复杂的同步逻辑。在C++中,我们使用`std::condition_variable`。 3. **信号量...

    Visual Basic 6.0建立多线程程序就是这么简单

    ' 建立线程2 hThread1 = CreateThread(0&, 0&, AddressOf AsyncThread1, 0&, 0&, hThreadID) CloseHandle hThread1 ' 建立线程3 hThread2 = CreateThread(0&, 0&, AddressOf AsyncThread2, 0&, 0&, hThreadID) ...

    c++多线程的创建挂起执行与销毁

    //线程2线程句柄 HANDLE hThread3; //线程3线程句柄 在增加三个结构体类型的变量,用做线程函数的参数传递; HANDLE hThread1; //线程1线程句柄 HANDLE hThread2; //线程2线程句柄 HANDLE hThread3; //线程3...

    线程的功能

    2. **线程的暂停** 线程的暂停功能允许我们在运行过程中控制线程的执行状态。在某些情况下,可能需要暂停线程以避免资源冲突或进行调试。然而,直接暂停线程并不总是安全的,因为可能会导致数据不一致或其他并发...

    编写程序,使用两个线程,一个队列,其中一个线程从键盘读取数据,放入到队列中,直到读取的数据是字符串quit则结束

    1. 编写程序,使用两个线程,一个队列, 其中一个线程从键盘读取数据,放入到队列中,直到读取的数据是字符串quit则结束,线程的任务就是循环读取数据直到特定的字符串quit。另外一个线程,不断的从队列中读取数据...

    操作系统实验-线程的创建和撤消.pdf

    在实验中,我们创建了两个线程,线程 1 和线程 2。我们使用 SuspendThread 和 ResumeThread 函数来挂起和恢复线程,并使用 GetExitCodeThread 函数来获取线程的退出码。实验结果表明,多线程编程可以提高系统的并发...

    AutoIt多线程Msgbox版

    MsgBox(0, "线程2", "这是线程2的消息") EndFunc CreateThread($thread1, ThreadFunction1()) CreateThread($thread2, ThreadFunction2()) While 1 Sleep(100) WEnd ``` 在这个例子中,`ThreadFunction1`和`...

    java多线程读取文件

    Java多线程读大文件 java多线程写文件:多线程往队列中写入数据

    易语言多线程

    "线程1"和"线程2"在这里可能指的是两个独立的线程实例。它们可以同时执行不同的任务,或者协同工作来完成一个复杂的任务。在设计程序时,需要合理分配线程间的资源,避免竞争条件和死锁等问题。 四、挂起线程 挂起...

    创建、增长并读取线程

    在本例中,可能需要线程1通过`notify()`唤醒线程2,告诉其数组已更新,而线程2则需要在`wait()`状态下,等待线程1的通知。此外,`join()`方法也可以用来确保线程1执行完毕后再执行线程2。 5. **异常处理**:多线程...

    网络编程6-多线程2.ppt

    《网络编程中的多线程技术》 多线程技术在网络编程中扮演着至关重要的角色,它允许程序同时执行多个任务,提高了系统的效率和响应性。本文将深入探讨多线程的概念、创建方法以及互斥与同步机制。 首先,我们理解...

    多线程编程死锁和事件对象设置线程顺序.rar_4 3 2 1_stepaqr_线程

    值得注意的是,偶数线程(线程2、4、6、8)的激活由奇数线程完成,这是因为线程9之后没有更大的奇数线程,所以它激活了最后一个线程10。 这种设计模式有助于避免线程之间的竞争,因为它规定了明确的执行顺序。此外...

    perl实现多线程详解[整理].pdf

    2. 使用 async 语句创建新线程 3. 使用锁机制来保护共享资源 4. 使用 join()方法等待线程的执行结果 Perl 语言中多线程实现的应用场景包括: 1. 网络编程:使用多线程可以提高网络编程的效率和响应速度。 2. 数据...

    Window下多线程编程、Linux下多线程编程-多线程实验bistu

    (1)实现多线程字符输出,存在三个线程,线程1用来监听用户输入和其他两个线程的监听器,线程2的主要内容为每隔一段时间,输出“hello 2”字符串,线程3的主要内容为每隔一段时间,输出“hello 3”字符串。...

    Linux 多线程介绍

    线程1在设置g_Flag后应解锁互斥量,让线程2可以继续执行,而线程2在设置g_Flag后应发送一个信号,唤醒等待的主线程。主线程在等待过程中会释放互斥量,确保线程2可以执行。 总之,Linux多线程编程是一种高效利用...

Global site tag (gtag.js) - Google Analytics