Java 多线程编程学习(一)

本文介绍了Java中实现多线程的两种方式:继承Thread类和实现Runnable接口,并通过示例展示了如何创建和启动线程,同时讨论了实例变量在多线程环境中的共享与不共享问题及线程安全解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结

构的基础。线程是在进程中独立运行的子任务,CPU以不确定的方式,或者说是以随机的时间来调用线程中的run方法。

 

一、使用多线程

       实现多线程编程的方式主要有两种,一种是继承Thread类,另一种是实现Runnable接口。

 

1.继承Thread类

①调用Thread.java类中的start方法:

通知“线程规划器”此线程已经准备就绪,等待调用线程对象的run()方法。

这个过程其实就是让系统安排一个时间来调用Thread中的run()方法,也就是使线程得到运行,启动线程,具有异步执行的效果。

 

②调用Thread.java类中的run方法:

由main主线程来调用run()方法,也就是必须等run()方法中的代码执行完后才可以执行后面的代码,具有同步执行的效果


public class MyThread extends Thread {

	@Override
	public void run(){
		try{
			for(int i = 0; i < 10; i++){
				int time = (int) (Math.random() * 1000);
				Thread.sleep(time);
				System.out.println("run=" + Thread.currentThread().getName());
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}

	
	public static void main(String[] args) {
		try{
			MyThread t = new MyThread();
			t.setName("mythread");
			t.start();   //通知“线程规划器”此线程已经准备就绪,等待调用线程对象的run方法
			//t.run();     //由main主线程来调用run()的方法,同步
			
			for(int i = 0; i < 10; i++){
				int time = (int) (Math.random() * 1000);
				Thread.sleep(time);
				System.out.println("run=" + Thread.currentThread().getName());
			}	
		}catch(InterruptedException e){
			e.printStackTrace();
		}

	}

}

注意:执行start()方法的顺序不代表线程启动的顺序。

 

2.实现Runnable接口

       如果欲创建的线程类已经有一个父类了,这时就不能再继承自Thread类了, 因为Java不支持多继承,所以就需要实现Runnable接口来应对这样的情况。

public class MyThread implements Runnable {

	@Override
	public void run() {
		System.out.println("运行中");
		
	}
	
	public static void main(String[] args) {
		Runnable runnable = new MyThread();
		Thread t = new Thread(runnable);
		t.start();
		System.out.println("运行结束");
	}
}

注意:Thread.java类也实现了Runnable接口,意味着构造函数Thread(Runnable target)不光可以传入Runnable接口的对象,还可以传入一个Thread类的对象,从而将一个Thread对象中的run()方法交由其他的线程进行调用。

 

3.实例变量与线程安全

      自定义线程类中的实例变量针对其他线程可以有共享与不共享之分,这在多个线程之间进行交互时是很重要的一个技术点

 

3.1变量不共享

      此示例一共创建了3个线程,每个线程都有各自的count变量,自己减少自己的count变量的值。这样的情况并不存在多个线程访问同一个实例变量的情况。

public class MyThread extends Thread{

	private int count = 5;
	public MyThread(String name){//构造函数
		super();
		this.setName(name);  //设置线程名称
	}
	@Override
	public void run(){
		super.run();
		while(count > 0){
			count--;
			System.out.println("由 " + this.currentThread().getName() +
					" 计算,count=" + count);
		}
	}
	
	public static void main(String[] args) {
		MyThread a = new MyThread("A");
		MyThread b = new MyThread("B");
		MyThread c = new MyThread("C");
		a.start();
		b.start();
		c.start();

	}

}

3.2 变量共享

       共享数据的情况就是多个线程可以访问同一个变量。

public class MyThread extends Thread{

	private int count = 5;
	@Override
	public void run(){
		super.run();
		/* 此示例不要用循环,因为使用同步后其他线程就得不到运行的机会了,
		 * 一直由一个线程进行减法运算*/
        count--;
		System.out.println("由 " + this.currentThread().getName() +
					" 计算,count=" + count);
		
	}
	
	public static void main(String[] args) {
		MyThread mythread = new MyThread();
		Thread a = new Thread(mythread,"A");
		Thread b = new Thread(mythread,"B");
		Thread c = new Thread(mythread,"C");
		Thread d = new Thread(mythread,"D");
		Thread e = new Thread(mythread,"E");
		a.start();
		b.start();
		c.start();
		d.start();
		e.start();

	}

}

 

原因:

       上图结果因为几个线程间对共享变量count执行的操作count--并不是原子操作,从而产生了“非线程安全”的问题。

解决方法:

       在Mythread的run()方法前加入synchronized关键字,将run()方法加锁,只有拿到“钥匙”的线程可以进入“临界区”。(详见操作系统的概念)

package Thread_01;

public class MyThread extends Thread{

	private int count = 5;
	@Override
	synchronized public void run(){  //将run()方法加上同步锁
		super.run();
		/* 此示例不要用循环,因为使用同步后其他线程就得不到运行的机会了,
		 * 一直由一个线程进行减法运算*/
        count--;
		System.out.println("由 " + this.currentThread().getName() +
					" 计算,count=" + count);
		
	}
	
	public static void main(String[] args) {
		MyThread mythread = new MyThread();
		Thread a = new Thread(mythread,"A");
		Thread b = new Thread(mythread,"B");
		Thread c = new Thread(mythread,"C");
		Thread d = new Thread(mythread,"D");
		Thread e = new Thread(mythread,"E");
		a.start();
		b.start();
		c.start();
		d.start();
		e.start();

	}

}
加上同步锁后的结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值