`

线程相关知识

阅读更多

进程本质上是一个执行的程序。
每个进程都有自己独立的一块内存空间、一组系统资源。在进程概念中,每一个进程的内部数据和状态都是完全独立的。
线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制,但与进程进程不同的是,同类的多个线程是共享同一块内存空间和一组内存空间和一组系统资源的,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈。
多线程是指在单个程序中可以同时运行多个不同的线程,执行不同的任务。多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行。
要产生一个线程,有两种方法:
1.需要从java.lang.Thread类派生一个新的线程类,重载它的run()方法。
2.实现Runnable接口,重载Runnable接口中的run()方法。
class NewThread extends Thread
{
 NewThread(){
  super("Thread Demo");
  System.out.println("New thread :"+getName());
 }
 
 public void run(){
  while(true){
   System.out.println(Thread.currentThread().getName()+"  is running");//静态方法
  
  }
 }
}

class ThreadDemo{
 public static void main(String[] args){
  NewThread thd  = new NewThread();
  thd.start();
 
 }

}
=================================================================================================================
class NewThread implements Runnable{

 public void run(){
  for(int i = 10;i>0;i--){
   try{
    System.out.println("left time ;"+i);
    Thread.sleep(1000);
    
   }catch(InterruptedException e){
    System.out.println(e.getMessage());
   }
  }
  System.out.println("game is over,bye!");
 }

}


class ThreadDemo{
 public static void main(String [] args){
  NewThread newthread = new NewThread();
  Thread thd = new Thread(newthread,"Thread Demo");
  thd.start();
 }

}

由于操作系统在调度线程的时候并不是按顺序进行的,而是将时间片轮流分给每一个线程,具体每一次分给哪个线程也是不确定的,但可以保证在很短的时间内,每一个线程都有机会被执行的机会。

火车票问题,用线程的方式来解决

class MutliThread implements Runnable{
 private int ticket =100;
 
 public void run(){
  while(ticket>0){
   System.out.println(ticket -- +" is saled by "+Thread.currentThread().getName());
  
  }
  
 }

}


class MutliThreadDemo{
 public static void main(String [] args){
 
  MutliThread m = new MutliThread();
  Thread t1 = new Thread(m,"window 1");
  Thread t2 = new Thread(m,"window 2");
  Thread t3 = new Thread(m,"window 3");
  t1.start();
  t2.start();
  t3.start();
 }

}

Java中,线程的优先级是介于Thread.MIN_PRIORITY到Thread.MAX_PRIORITY这两个常量之间的某个整数数值(1-10)。默认情况下,线程的优先级都是5,在java中用NORM_PRIORITY来表示。其中,MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORIYT均是Thread类的静态整型常量。

当利用某一线程又创建了一个新线程对象时,这个新线程将拥有与创建它的线程一样的优先级。

线程的生命周期
1.创建状态  当一个线程被实例化后,它就处于创建状态,直到调用start()方法。当一个线程处于创建状态时,它仅仅是一个空的线程对象,系统不为它分配资源。在这个状态下,线程还不是活的。
Thread myThread = new MyThreadClass();
 
2.可运行状态 对于处于创建状态的线程来说,只要对其调用start()方法,就可以使该线程进入可运行状态。当一个线程处于可运行状态时,系统为这个线程分配它所需要的系统资源,然后安排其运行并调用线程的run()方法。此时的线程具备了所有能够运行的条件,但是,此状态的线程并不一定马上就被执行。这是因为目前所使用的计算机大多都是单处理器的,因此,要想在同一时刻运行所有的处于运行状态的线程是不可能的。
myThread.start();

3.不可运行状态
可以认为,在下面列出的条件之一发生时,线程进入不可运行状态。
(1)调用了sleep()方法;
(2)为等候一个条件变量,线程调用了wait()方法;
(3)输入输出流中线程被阻塞。
不可运行状态也可以称为阻塞状态(Blocked)。如:sleep的时间到达、得到条件变量之后使用了notify()方法或者notifyAll()方法唤醒了waiting中的一个或所有线程、获得了需要的I/O资源等。

4.消亡状态
一般来讲,线程的run()方法执行完毕时,该线程就被视为进入了消亡状态。一个处于消亡状态的线程不能再进入其他状态,即使对它调用start()方法也无济于事。可以通过两种方法使线程进入消亡状态:自然撤销(线程执行完)或是强行中止。


等待一个线程执行结束后再运行另一个线程,有两种方法:
方法一:
class NewThread implements Runnable{
 
//省略
}

class ThreadTestDemo{
 public static void main(String []args){
 
  NewThread n = new NewThread();
  
  Thread t1 = new Thread(n,"thread1");
  Thread t2 = new Thread(n,"thread2");
  t1.start();
  while(t1.isAlive()){
   try{
    Thread.sleep(100);//让主线程休眠100毫秒,程序不往下执行。
   }catche(InterruptedException e){
    e.printStackTrace();
   }
  }
  t2.start();
 }

}
===================================================================================================================
方法二:

class NewThread implements Runnable{
 
//省略
}

class ThreadTestDemo2{

 public static void main(String []args){
  NewThread n = new NewThread();
  
  Thread t1 = new Thread(n,"thread1");
  Thread t2 = new Thread(n,"thread2");
  
  t1.start();
  try{
   t1.join();//当前线程等待线程t1执行完后再继续往下执行。
  }catch(InterruptedException e ){
   e.printStackTrace();
  }
  t2.start();
 }
}

线程中断:(用户线程在调用interrupt()方法后,并没有被中断,而是继续执行,直到人为地中止。m1.interrupt()语句只有当线程发生阻塞时才有效。它的作用就是抛出一个InterruptedException类的异常对象,是try...catch语句捕获异常,并对其进行处理。)
class MyThread extends Thread{
 boolean stop = false;
 
 public void run(){
  while(!stop){
   System.out.println(getName()+" is running");
   try{
    sleep(1000);
   }catch(InterruptedException e ){
    e.printStackTrace();
   }
  }
  System.out.println("Thread is exiting...");
 }
}

class InterruptThreadDemo{
 public static void main(String [] args){
 
  MyThread m = new MyThread();
  System.out.println("Starting thread ...");
  m.start();
  Thread.sleep(3000);
  System.out.println("Interrupt thread...");
  m.stop = true;//修改共享变量
  Thread.sleep(3000);//主线程休眠以观察线程中断后的情况
  System.out.println("Stopping application ...");
 }
}


同步:
情况一:使用同步代码块

class SaleTickets implements Runnable{
 private String ticketNo = "100750";//车票编号
 private int ticket = 1;//共享私有成员,编号为100750的车票数量为1
 public void run(){
 
  System.out.println(Thread.CurrentThread().getName() + " is saling Thicket"+ticketNo);//
  //下面同步代码块中的代码为关键代码,用synchronized关键字来标识
  synchronized(this){
   if(ticket>0){
    try{
     Thread.sleep((int)(Matn.random()*1000));
    }catch(InterruptedException e){
     e.printStackTrace();
    }
    ticket = ticket - 1;
    System.out.println("ticket is saled by "+ Thread.currentThread().getName()+",amount is :"ticket);
   }
   else{
    System.out.println("Sorry "+Thread.currentThread().getName()+", Ticket" +ticketNo +"is saled");
   }
  }
 }
}

class SynchronizedDemo{
 public static void main(String [] args){
  SaleTicket m = new SaleTicket();
  Thread t1 = Thread(m,"System1");
  Thread t2 = Thread(m,"System2");
  t1.start();
  t2.start();
 }
}


情况二:使用同步方法

class SaleTickets implements Runnable{
 private String ticketNo = "100750";//车票编号
 private int ticket = 1;//共享私有成员,编号为100750的车票数量为1
 public void run(){
 
  System.out.println(Thread.CurrentThread().getName() + " is saling Thicket"+ticketNo);//
  //下面同步代码块中的代码为关键代码,用synchronized关键字来标识
  sale();
 }
 public synchronized void sale(){ //同步方法中的代码为关键代码
 
    if(ticket>0){
    try{
     Thread.sleep((int)(Matn.random()*1000));
    }catch(InterruptedException e){
     e.printStackTrace();
    }
    ticket = ticket - 1;
    System.out.println("ticket is saled by "+ Thread.currentThread().getName()+",amount is :"ticket);
   }
   else{
    System.out.println("Sorry "+Thread.currentThread().getName()+", Ticket" +ticketNo +"is saled");
   }
 }
}

 

class SynchronizedDemo{
 public static void main(String [] args){
  SaleTicket m = new SaleTicket();
  Thread t1 = Thread(m,"System1");
  Thread t2 = Thread(m,"System2");
  t1.start();
  t2.start();
 }
}

这两种方法的区别:
简单地说,用synchronized关键字修饰的方法不能被继承。或者说,如果父类的某个方法使用了synchronized关键字修饰,那么在其子类中该方法的重载方法是不会继承其同步特征的。如果需要在子类中实现同步,应该重新使用synchronized关键字来修饰。

注意:在多线程的程序中,虽然可以使用synchronized关键字来修饰需要同步的方法,但是并不是每一个方法都可以被其修饰的。比如,不要同步一个线程对象的run()方法,因为每一个线程运行都是从run()方法开始的。在需要同步的多线程程序中,所有线程共享这一方法,由于该方法又被synchronized关键字所修饰,因此一个时间内只能有一个线程能够执行run()方法,结果所有线程都必须等待前一个线程结束后才能执行。

死锁问题:即由于两个或多个线程都无法得到相应的锁二造成的两个线程都等待的现象。这种现象主要是因为相互嵌套synchronized代码段而造成的。


共享池解决生产者和消费者问题

class SyncStack{

 private int index = 0;
 private char[] buffer = new char[5];
 
 public synchronized void push(char c){
 
  if(index == buffer.length){
   try{
    this.wait();
   }catch(InterruptedException e ){
    e.printStackTrace();
   }
  }
  
  buffer[index] = c;
  index++;
  this.notify();
 }

 public synchronized char pop(){
  if(index == 0){
   try{
    this.wait();
   }catch(InterruptedException e ){
    e.printStackTrace();
   }
  }
  this.notify();
  index --;
  return buffer[index];
 }
}

class Producer implements Runner{
 SyncStack s;
 public Producer(SyncStack s){
  this.s = s;
 }
 
 public void run(){
  char ch;
  for(int i = 0;i<5;i++){
   try{
    Thread.sleep((int)(Math.random()*1000));
   
   }catch(InterruptedException e){
    e.printStackTrace();
   }
   ch = (char)(Math.random()*26+A);
   s.push(ch);
   System.out.println("Push" + ch +"in Stack");
  }
 }
}


class Consumer implements Runnable{
 SyncStack s ;
 
 public Consumer(SyncStack s){
  this.s = s;
 }
 
 public void run(){
  char ch;
  
  for(int i=0;i<5;i++){
   try{
    Thread.sleep((int)(Math.random()*3000));
   }catch(InterruptedException e){
    e.printStackTrace();
   }
   ch =s.pop();
   System.out.println("Pop" + ch +"  from stack");
  }
 }
}

public class Communication{
 public static void main(String[] args){
  SyncStack stack = new SyncStack();
  Thread t1 = new Thread(new Producer(stack));
  Thread t2 = new Thread(new Producer(stack));
  t1.start();
  t2.start();
 }

}

分享到:
评论

相关推荐

    Java多线程相关知识总结

    ### Java多线程相关知识总结 #### 一、基本概念 多线程是现代编程语言中一项非常重要的特性,尤其在Java这样的高级语言中更是如此。简单来说,**多线程**指的是在一个程序中能够同时运行多个不同的执行路径。下面...

    Android-android简单的链式线程切换工具类简单适用可用于学习线程相关知识

    本文将深入探讨由用户分享的"ThreadUtils"工具类,它为Android开发者提供了一种简单的链式线程切换方法,有助于理解和应用线程相关知识。 首先,让我们了解Android中的线程模型。主线程,也称为UI线程,负责处理与...

    java多线程相关知识导图

    java多线程相关知识导图

    多线程相关知识源码-----多线程案例源码

    多线程相关知识源码-----多线程案例源码

    VC 线程基础知识总结

    ### VC 线程基础知识总结 #### 一、线程概念与重要性 在计算机科学领域,线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。程序员可以通过多线程技术,实现并发执行任务,...

    C# 线程相关知识总结

    初识线程 线程是一个独立的运行单元,每个进程内部都有多个线程,每个线程都可以各自同时执行指令。每个线程都有自己独立的栈,但是与进程内的其他线程共享内存。但是对于.NET的客户端程序(Console,WPF,WinForms...

    进程与线程相关知识

    进程相关的知识,线程相关的知识,进程与线程、进程与线程、进程与线程

    JAVA中的线程知识点整理

    以下是对Java线程相关知识点的详细说明: 1. **线程的创建与执行** - 创建线程有两种方式:继承`Thread`类或者实现`Runnable`接口。继承`Thread`直接重写`run()`方法,而实现`Runnable`接口则需要提供一个包含业务...

    Java多线程知识点总结

    了解线程池的概念也是Java多线程编程中的一个重要知识点。线程池是一种多线程处理形式,它将线程和任务的概念分离开来,能够有效管理线程资源,减少线程创建和销毁的开销,提高程序性能。Java中可以通过Executors类...

    多线程相关知识梳理与示例代码

    Windows没有单独的调度模块或程序,调度的代码是在内核中实现的,广泛分布在内核中那些与调度相关的事件发生的地方。这些负责调度的程序被总称为“内核的调度器”。线程调度发生在DPC/Dispatch级别。

    有关线程知识

    根据提供的文件信息,我们可以从中提炼出关于线程管理和信号量操作的相关知识点。下面将详细解释这些知识点,并尽可能地提供丰富的信息。 ### 线程基础知识 #### 什么是线程? 线程是操作系统能够进行运算调度的...

    C#多线程基础知识资料合辑(基础部分)

    以下是一些关于C#多线程的基础知识: 1. **线程的创建**:在C#中,可以使用`System.Threading.Thread`类来创建新的线程。通过实例化`Thread`类并提供一个代表新线程执行的委托,即可启动新线程。例如,`new ...

    多线程面试相关知识点

    多线程 1. 什么是线程: 线程就是程序中单独顺序的流控制。线程本身不能运行,它只能用于程序中。 2. 什么是多线程: 多线程则指的是在单个程序中可以同时运行多个不同的线程执行不同的任务. 说明: 线程是程序内...

    多线程知识总结

    ### 多线程知识总结 #### 一、线程基础概念 **线程状态:** 在探讨多线程之前,我们需要了解线程的基本状态转换。一个典型的线程生命周期包括以下几个阶段: 1. **Start(启动):** 当线程被创建后调用`start()`...

    多线程基础知识

    本知识点主要围绕多线程的基础知识展开,包括线程的概念、创建与管理、同步与通信以及其在实际开发中的应用。 首先,我们要理解什么是线程。线程是操作系统调度的基本单位,它是进程内部的一个执行单元。一个进程中...

    VC 线程 创建 操作 同步 终止 UI线程等各种线程例子

    下面将详细介绍标题和描述中涉及的线程相关知识点。 1. **创建线程**: - 使用`CreateThread`函数可以创建一个新的线程。这个函数需要指定线程函数的入口地址、参数、初始堆栈大小等信息。 - 也可以使用`_...

    线程——基本线程的应用和线程调用控件

    通过理解并掌握上述线程相关知识,开发者可以编写出高效、稳定且响应迅速的多线程程序。在实际应用中,正确地使用线程和有效地管理线程调用,对于提升软件性能和用户体验至关重要。在后续的学习中,你可以通过实践和...

    线程基本知识(英文)

    总之,理解和掌握线程的基本知识对于开发多线程应用至关重要。正确使用线程可以提高程序的并发性和效率,但同时也需要处理好线程同步、资源管理和通信等问题,以确保程序的稳定性和正确性。在MFC框架中,利用...

    线程源代码线程源代码

    以下是基于这个源代码的线程相关知识点的详细说明: 1. **线程创建**:在`CWorkerThread`构造函数中,使用`CreateThread`函数创建了一个新的线程。`CreateThread`函数接受多个参数,包括线程安全属性、初始堆栈大小...

Global site tag (gtag.js) - Google Analytics