JAVA多线程学习笔记

简介:

JAVA多线程学习笔记

多线程的概念
程序、进程与线程:
程序:一段静态的代码,它是应用软件执行的蓝本。
进程:程序的一次动态执行过程(动态概念),它对应了从代码加载、执行到执行完毕的完整过程。一个程序可以被多次加载到系统的不同区域分别执行,形成不同的进程。
线程:比进程更小的执行单位(动态概念)。一个进程在执行过程中可产生多个线程,形成多条执行线索。每个进程都有一段专用的内存区,并以PCB(Process Control Block)作为它存在的标志;而一个进程中的所有线程可以共享该进程的同一个地址空间和操作系统资源,并利用这些共享单元实现数据交换、实时通信与必要的同步操作。因此多线程占用系统资源少、线程间通信快。

一、.线程的状态及其转换

1.线程的状态:

 

 

2  创建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象属于新建状态。   Thread  myThread=new MyThreadClass();
3  就绪:处于创建状态的线程被启动后将进入线程队列等待CPU时间片,此时它已具备了运行条件,一旦被分配了CPU就可脱离创建它的主线程独立开始其生命周期,另外处于阻塞状态的线程被解除阻塞后以及处于运行态的线程时间片到后也将进入就绪态。
4  运行:就绪态的线程被调度并获得CPU时进入运行态,并自动执行run()方法。
5  阻塞:正在执行的线程若被人为挂起或系统原因必须停止运行将进入阻塞状态。如:该线程正等待I/O操作,调用该线程的sleep()方法、wait()方法、suspend()方法等。
6  死亡:正常终止,就是正常运行run()方法后终止;异常终止,如调用stop()方法或destroy()方法终止线程。

二、多线程实现的两种方法

继承Thread类、实现Runnable接口(此方法比较灵活,因为实现Runnable接口的类还可以继承其他类)。
1  继承Thread类
通过定义java.lang包中的Thread类的子类并在子类中重写run()方法。由于java不能多重继承,此方法简单但不灵活。Thread类的构造函数及主要方法如下:
public Thread():产生一个名字自动生成的线程,名字形式为Thread_1、Thread_2、、、;
public Thread(Runnable target):生成一个指定目标对象的线程;
public Thread(String name):生成一个指定名字的线程;
public Thread(ThreadGroup group,Runnable target):生成一个指定线程组和目标对象的线程;
public Thread(ThreadGroup group,String name):生成一个指定线程组和名字的线程。
通过继承Thread类实现多线程示例:ThreadTest.java程序中subThread类继承了Thread类,先定义了一个构造函数调用父类的构造函数给该线程置名,然后重写了run()方法,使线程运行时每输出一个循环变量后休眠一段随机时间,让另一个线程运行,一个线程的run()方法结束前输出该线程的结束信息。
2  实现Runnable接口
Runnable接口只有一个run()方法,要实现此接口就必须定义run()方法的具体内容,方法体内可定义用户要做的操作。然后以这个实现了Runnable接口的类为参数创建Thread类的对象,也就是用Runnable接口的目标对象初始化Thread类的对象,如此就可把用户实现的run()方法继承过来。

程序UseRunnable.java

import java.awt.*;import java.applet.Applet;
public class UseRunnable extends Applet implements Runnable
{Label prompt1=new Label("第一个子线程");
Label prompt2=new Label("第二个子线程");
TextField threadFirst=new TextField(14);
TextField threadSecond=new TextField(14);
Thread thread1,thread2; int count1=0,count2=0;
public void init(){add(prompt1);add(threadFirst);
                   add(prompt2);add(threadSecond);}
public void start()
{thread1=new Thread(this,"FirstThread");thread2=new Thread(this,"SecondThread");
 thread1.start();thread2.start();}
public void stop(){if(thread1.isAlive())thread1.stop();
                 if(thread2.isAlive())thread2.stop();}
public void run(){String currentRunning;
while(true){try{Thread.sleep((int)(Math.random()*3000));}
            catch(InterruptedException e){}
currentRunning=Thread.currentThread().getName();
if(currentRunning.equals("FirstThread"))
{count1++;threadFirst.setText("线程1第"+count1+"次被调度");}
else if(currentRunning.equals("SecondThread"))
{count2++;threadSecond.setText("线程2第"+count2+"次被调度");}
if(count1>10)thread1.stop();
if(count2>10)thread2.stop();}}}
三、 多线程的基本控制
在控制线程从一种状态转入另一种状态时,必须调用正确的方法,否则将产生异常。线程各状态和相互转换时需调用的方法如下:

 

 

除了注意状态转换时需调用的方法外,为使多个线程之间能协调工作,必须控制线程的互斥、同步及死锁问题。
互斥:一组并发进程中一个或多个程序段,因共享某一公用资源而导致它们必须以一个不允许交叉执行的单位执行。即不允许两个以上共享该公用资源的并发进程同时进入临界区。
同步:一组并发进程因直接制约而互相发送消息,进行相互合作,互相等待,使得各进程按一定的执行速度执行的过程,称为进程间同步。
死锁:在多个进程并行执行时,当某进程提出资源申请后,使得若干进程在无外力作用下,永远得不到所需要的资源,不能再继续运行的情况。
如生产者与消费者问题:生产的产品存入仓库,消费时从仓库取出产品。当仓库满时再生产将无处可放,而当仓库空时再消费将取不到产品。采用同步策略可协调生产与消费.。
见程序StackTest.java

class stack 
{int sip=0; String data[]=new String[6];
 public synchronized void push(String strCell)
 {while(sip==data.length)
   {try
      {this.wait();}
    catch(InterruptedException e){}
   } //while
  this.notify();
  data[sip]=strCell;
  sip++;
 }//push()

 public synchronized String pop()
 {while(sip==0)
   {try
      {this.wait();}
    catch(InterruptedException e){}
   }
  this.notify();
  sip--;
  return data[sip];
 }
}
 
class Producer implements Runnable
{stack stackOne;
 public Producer(stack s)
 {stackOne=s;}

 public void run()
 {String strTemp=null;
  for(int i=0;i<20;i++)
   {strTemp=String.valueOf(i+1);
    stackOne.push(strTemp);
    System.out.println("Produced:"+strTemp);
    try
      {Thread.sleep((int)(Math.random()*100));}
    catch(InterruptedException e){}
   }//for
 }//run()
}

class Consumer implements Runnable
{stack stackOne;
 public Consumer(stack s)
 {stackOne=s;}

 public void run()
 {String strTemp=null;
  for(int i=0;i<20;i++)
   {strTemp=stackOne.pop();
    System.out.println("Consumed:"+strTemp);
    try
      {Thread.sleep((int)(Math.random()*100));}
    catch(InterruptedException e){}
   }//for
 }//run()
}

public class StackTest
{public static void main(String args[])
 {stack s1=new stack();
  Runnable producer=new Producer(s1);
  Runnable consumer=new Consumer(s1);
  Thread p=new Thread(producer);
  Thread c=new Thread(consumer);
  p.start();c.start();
 }
}
程序中对堆栈进行了synchronized处理,其作用是对共享资源加锁,即方法中的所有对象在任何一个时刻只能由一个线程访问。生产前检查堆栈情况,若满则等待(wait())并释放互斥锁,否则可生产;消费前先检查堆栈,若空则等待并释放互斥锁,否则可消费。唤醒wait()采用notify()方法,该方法将随机使等待队列中的一个线程离开等待队列进入就绪状态。也可以在方法体内单独对某个对象加锁。Produser是生产者模型,Consumer是消费者模型,他们实现了Runnable接口,作为目标对象来创建生产者和消费者线程对象。生产者每次随机生产20个数字并压入堆栈,间隔时间为随机间隔0~100ms,靠调用sleep()方法完成。消费者共消费20次,其间隔时间也是随机间隔0~100ms。

 





 本文转自 李晨光 51CTO博客,原文链接:http://blog.51cto.com/chenguang/461423,如需转载请自行联系原作者



相关文章
|
12天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第11天】 在Java中,高效的并发编程是提升应用性能和响应能力的关键。本文将探讨Java并发的核心概念,包括线程安全、锁机制、线程池以及并发集合等,同时提供实用的编程技巧和最佳实践,帮助开发者在保证线程安全的前提下,优化程序性能。我们将通过分析常见的并发问题,如竞态条件、死锁,以及如何利用现代Java并发工具来避免这些问题,从而构建更加健壮和高效的多线程应用程序。
|
4天前
|
安全 Java
深入理解 Java 多线程和并发工具类
【4月更文挑战第19天】本文探讨了Java多线程和并发工具类在实现高性能应用程序中的关键作用。通过继承`Thread`或实现`Runnable`创建线程,利用`Executors`管理线程池,以及使用`Semaphore`、`CountDownLatch`和`CyclicBarrier`进行线程同步。保证线程安全、实现线程协作和性能调优(如设置线程池大小、避免不必要同步)是重要环节。理解并恰当运用这些工具能提升程序效率和可靠性。
|
5天前
|
安全 Java
java多线程(一)(火车售票)
java多线程(一)(火车售票)
|
5天前
|
安全 Java 调度
Java并发编程:深入理解线程与锁
【4月更文挑战第18天】本文探讨了Java中的线程和锁机制,包括线程的创建(通过Thread类、Runnable接口或Callable/Future)及其生命周期。Java提供多种锁机制,如`synchronized`关键字、ReentrantLock和ReadWriteLock,以确保并发访问共享资源的安全。此外,文章还介绍了高级并发工具,如Semaphore(控制并发线程数)、CountDownLatch(线程间等待)和CyclicBarrier(同步多个线程)。掌握这些知识对于编写高效、正确的并发程序至关重要。
|
5天前
|
安全 Java 程序员
Java中的多线程并发编程实践
【4月更文挑战第18天】在现代软件开发中,为了提高程序性能和响应速度,经常需要利用多线程技术来实现并发执行。本文将深入探讨Java语言中的多线程机制,包括线程的创建、启动、同步以及线程池的使用等关键技术点。我们将通过具体代码实例,分析多线程编程的优势与挑战,并提出一系列优化策略来确保多线程环境下的程序稳定性和性能。
|
6天前
|
缓存 分布式计算 监控
Java并发编程:深入理解线程池
【4月更文挑战第17天】在Java并发编程中,线程池是一种非常重要的技术,它可以有效地管理和控制线程的执行,提高系统的性能和稳定性。本文将深入探讨Java线程池的工作原理,使用方法以及在实际开发中的应用场景,帮助读者更好地理解和使用Java线程池。
|
6天前
|
存储 安全 Java
Java中的容器,线程安全和线程不安全
Java中的容器,线程安全和线程不安全
15 1
|
6天前
|
Java 开发者
Java中多线程并发控制的实现与优化
【4月更文挑战第17天】 在现代软件开发中,多线程编程已成为提升应用性能和响应能力的关键手段。特别是在Java语言中,由于其平台无关性和强大的运行时环境,多线程技术的应用尤为广泛。本文将深入探讨Java多线程的并发控制机制,包括基本的同步方法、死锁问题以及高级并发工具如java.util.concurrent包的使用。通过分析多线程环境下的竞态条件、资源争夺和线程协调问题,我们提出了一系列实现和优化策略,旨在帮助开发者构建更加健壮、高效的多线程应用。
7 0
|
7天前
|
缓存 监控 Java
Java并发编程:线程池与任务调度
【4月更文挑战第16天】Java并发编程中,线程池和任务调度是核心概念,能提升系统性能和响应速度。线程池通过重用线程减少创建销毁开销,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。任务调度允许立即或延迟执行任务,具有灵活性。最佳实践包括合理配置线程池大小、避免过度使用线程、及时关闭线程池和处理异常。掌握这些能有效管理并发任务,避免性能瓶颈。
|
8天前
|
设计模式 运维 安全
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第15天】在Java开发中,多线程编程是提升应用程序性能和响应能力的关键手段。然而,它伴随着诸多挑战,尤其是在保证线程安全的同时如何避免性能瓶颈。本文将探讨Java并发编程的核心概念,包括同步机制、锁优化、线程池使用以及并发集合等,旨在为开发者提供实用的线程安全策略和性能优化技巧。通过实例分析和最佳实践的分享,我们的目标是帮助读者构建既高效又可靠的多线程应用。

热门文章

最新文章