Java中进程和线程基础

java中的进程和线程

java中的进程可以看成是系统资源和程序代码的执行位置的集合。进程是系统分配内存的最小单位。线程之间很难进行通信。

java中的线程是比进程更小的执行单位,一个进程可以包含一个或多个线程,多个线程共享进程的独立的JVM内存单元,从而涉及到数据共享及操作的冲突等相关问题,因此在进行多线程编程时要特别注意线程的安全。

线程的生命周期一般分为五个状态,分别为创建(new)、就绪(Runnable)、运行(running)、阻塞(Blocked)、死亡(Dead)五种。

java的线程类

java中的线程类为java.lang.Thread,任何一个Thread的实例对象都通过调用start方法来启动一个线程,而线程中的run方法则是线程启动后自动运行用于实现功能的业务方法。

Thread常用的构造器有三种
public Thread();
public Thread(Runnable target);
public Thread(Runnable target,String name) ;
多线程:在一个应用程序中,有多个顺序流同时执行。(线程:顺序执行的代码)

Thread的常用方法如下:
public Thread() 构造一个新的线程对象(Thread类的构造函数),默认名为Thread-n,n是从0开始递增的整数
public Thread(Runnable target) 构造一个新的线程对象,以一个实现Runnable接口的类的对象为参数,默认名为Thread-n,n是从0开始递增的整数
public Thread(String name) 构造一个线程对象,并同时指定线程名
public static Thread currentThread() 返回一个当前正在运行的线程对象
public static void yield() 使当前线程对象暂停,允许别的线程开始运行(注:yield:屈服)
public static void sleep(long millis) 使当前线程暂停运行指定毫秒数,但此线程并不失去已获得的锁
public void start() 启动线程,JVM将调用此线程的run方法,结果是将同时运行两个线程,当前线程和执行run方法的线程
public void run() Thread的子类应该重写此方法,内容应为该线程应执行的任务
public final void stop() 停止线程运行,释放该线程占用的对象锁
public void interrupt() 中断此线程
public final void join() 如果启动了线程A,调用join方法将等待线程A死亡才能继续执行当前线程
public final void join(long millis) 如果此前启动了线程A,调用join方法将等待指定毫秒数或线程A死亡才能继续执行当前线程
设置线程优先级
public final void setPriority( int newPriority) 设置线程优先级
public final void setDaemon(Boolean on) 设置是否为后台线程,如果当前运行线程均为后台线程则JVM停止运行。这个方法必须在start()方法前使用(注:daemon:后台程序)
public final void checkAccess() 判断当前线程是否有权力修改调用此方法的线程
public void setName(String name) 更改本线程的名称为指定参数
public final boolean isAlive() 测试线程是否处于活动状态,如果线程被启动并且没有死亡则返回true

创建线程有两种方式:
一,目标类来继承Thread类,重写run方法来创建自己的线程。调用start函数就开始执行线程代码。
从Thread类派生一个子类,并创建子类的对象。子类应该重写Thread类的run方法,写入需要在新线程中执行的语句段。调用start方法来启动新线程,自动进入run方法。举例的代码如下:

public class TestThread {

	public static void main(String[] args) {
		
		ThreadOne one = new ThreadOne();
		ThreadTwo two = new ThreadTwo();
		one.setName("线程一");
		two.setName("线程二");
		// 设置线程的优先级
		two.setPriority(Thread.MIN_PRIORITY);
		one.setPriority(Thread.MAX_PRIORITY);
		one.start();
		two.start();
		System.out.println("我是main方法");

	}
}
public class ThreadOne extends Thread {

	int count = 1;
	@Override
	public void run() {
		
		while(true){
			System.out.println("我是线程:"+this.getName());
			if(count ==10){
				Thread.yield();
				System.out.println("线程暂停");
			}
			count++;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
public class ThreadTwo extends Thread {

	@Override
	public void run() {

		while(true){
			System.out.println("我是线程 "+this.getName());
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}	
}

二,写一个类来实现Runnable接口,在初始化一个Thread类或者Thread子类的线程对象的时候 ,把该类的对象作为参数传递给那个线程对象。(其中由该类提供run方法),用Runable接口的好处是让多个Thread的实例共享此接口的run方法,从而使得线程间的通信更加方便。

public class TestRunnable {

	public static void main(String[] args) {
	
		Thread t0 = null;
		Thread t2 = null;
		MyRannble ran = new MyRannble(t0, t2);
		
	}
    public class MyRannble implements java.lang.Runnable {

	private Thread th0;
	private Thread th2;
	int sum = 0;// 存储累加和的结果
	int i = 1;// 循环变量
	public  MyRannble(Thread t0,Thread t2){
		
		if(t0 == null)
			th0 = new Thread(this); // th0 与 th2 共享一个实现Runnable接口的实例
		if(t2 == null)
			th2 = new Thread(this);
		th0.setName("线程一");
		th2.setName("线程二");
		th0.start();// 启动线程t0
		try {
			th0.join();// join方法将使此线程独占CPU资源,其他线程必需等待此线程执行完毕
		} catch (InterruptedException e) {
			e.printStackTrace();
		} 
		th2.start();// 启动线程t2
	}
	
	@Override
	public void run() {
			
		String thName = Thread.currentThread().getName();// 获取当前线程的名字
		while(i<=100){
			System.out.println("当前线程 "+thName+" 正在计算");
			sum+=i++;// 计算累加和
			System.out.println("当前的累加和是 "+sum);
			if(i==50 && thName.equals("线程一")){
				break;
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

线程之间的通信

在处理线程同步时,要做的第一件事就是要把修改数据的方法用关键字synchronized来修饰,一个方法使用关键synchronized修饰后,当一个线程A使用这个方法时,其他线程想使用这个方法时就必须等待,直到线程A使用完该方法.

使用synchronnized实现线程同步有三种机制,分别是同步代码块,对象同步锁和方法同步锁。

同步代码块:被同步的代码块在一个线程对象进行访问时,其他线程是没有访问权限的,只有这个当前线程对象完全执行完了这个代码块,释放了同步锁,其它线程才可以访问这个代码块。

public class SynCode implements Runnable {

	@Override
	public void run() {
		
		synchronized (this) {
			Thread current = Thread.currentThread();// 获取当前线程
			for(int i=1;i<=10;i++){
				
				System.out.println("当前执行同步代码块的线程名称是 "+current.getName());
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

对象同步锁:
1.对共享对象的访问必须同步,叫做条件变量
2.Java语言允许通过监视器使用条件变量实现线程同步
3.监视器阻止两个线程同时访问一个条件变量,它如同锁一样作用在数据上
4.线程一进入方法时获得监视器(加锁),当线程一的方法执行完毕后释放监视器(开锁),线程二的方法才能进入

public class SynObject implements Runnable {

	private Dog dog;
	
	public SynObject(){
		if(dog == null)
			dog = new Dog();
	}
	@Override
	public void run() {
		
		synchronized(dog){
			Thread current = Thread.currentThread();
			for(int i=1;i<=10;i++){
				
				System.out.println("线程 "+current.getName()+" 在修改dog的名字");
				dog.setName("卡尔"+i);
				System.out.println(dog.getName());
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

方法同步锁:
用synchrinized标识的方法为互斥方法。表明在任何给定的时候都只能有一个线程可以执行该方法(方法同步锁)。

public class SynMethod implements Runnable {

	private double money = 1000000;
	
	@Override
	public void run() {
		
		doMoney();
	}

	/**
	 * 同步方法
	 */
	private synchronized void doMoney(){
		
		Thread t = Thread.currentThread();
		for(int i=1;i<=10;i++){
			
			if(t.getName().equals("会计")){
				money+=i*10;
				System.out.println(t.getName()+"正在整理账户");
			}
			if(t.getName().equals("出纳")){
				money-=i*5;
				System.out.println(t.getName()+"正在支取钱");
			}
			System.out.println("当前账号金额是 "+money);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
发布了8 篇原创文章 · 获赞 2 · 访问量 501

猜你喜欢

转载自blog.csdn.net/qq_42003546/article/details/100041934