Java单线程和多线程详解

本文深入探讨Java中的单线程和多线程概念,分析它们的运行机制、优缺点及使用场景。通过实例讲解如何在Java中创建和管理线程,帮助开发者理解线程同步和通信的重要性。

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


  • 单线程

package com;

public class SingletonThread {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Thread thread = Thread.currentThread();
		thread.setName("单线程");
		System.out.println(thread.getName()+"正在运行");
		for (int i = 0; i < 10; i++) {
			System.out.println("线程正在休眠:"+i);
			try {
				thread.sleep(500);
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
				System.out.println("线程出现错误!");
			}
		}
		
	}

}

  • 多线程
        Java中有两种实现多线程的方式。一是直接继承Thread类,二是实现Runnable接口。那么这两种实现多线程的方式在应用上有什么区别呢?
1、继承Thread类,并重写run方法
    public class ThreadImpl {
	public static void main(String[] args) {
		Thread t1 = new ThreadTest("t1", 1000);
		Thread t2 = new ThreadTest("t2", 20000);
		Thread t3 = new ThreadTest("t3", 300000);
		
		t1.start();
		t2.start();
		t3.start();
	}
}
class ThreadTest extends Thread{
		private String name;
		private int ms;
		public ThreadTest(String name, int ms) {
			this.name = name;
			this.ms = ms;
		}
		public void run(){
			try {
				sleep(ms);
			} catch (Exception e) {
				// TODO: handle exception
			<span style="white-space:pre">	</span>System.out.println("线程中断异常");
			}
			System.out.println("名称为:"+name+",线程休眠:"+ms+"毫秒");
		}
		
	}

结果:
      名称为:t1,线程休眠:1000毫秒
      名称为:t2,线程休眠:20000毫秒
      名称为:t3,线程休眠:300000毫秒

从上面的代码中可看出,程序启动时总是会自动调用main()方法执行主线程,因此main()是创建和启动程序的地方,首先创建t1、t2、t3三个线程并传入了相应的参数,程序运行到t1.start(); 启动线程并自动调用run()方法,在run()方法中,sleep(1000)这个方法使t1线程暂停停止运行1000毫秒,之后线程才可以恢复运行,在t1休眠的状态里,把执行权交给t2,而不是等t1恢复运行后再让t2运行。 由此可以得出:一个线程对象只能启动一个线程,无论你调用多少遍start()方法,结果只有一个线程。

2、实现Runnable接口,并重写run方法

public class RunnableTest {
	public static void main(String[] args) {
        Runnable runnable=new MyThread();
        new Thread(runnable).start();
        new Thread(runnable).start();
        new Thread(runnable).start();
        new Thread(runnable).start();
    }
    
    public static class MyThread implements Runnable{
        //车票数量
        private int tickets=100;
        public void run() {
            while(tickets>0){
                System.out.println(Thread.currentThread().getName()+"卖出第  【"+tickets--+"】张火车票");
            }
        }  
    }
}

从结果上看每个票号都被打印了四次,即四个线程各自卖各自的100张票,而不去卖共同的100张票。这种情况是怎么造成的呢?我们需要的是,多个线程去处理同一个资源,一个资源只能对应一个对象,在上面的程序中,我们创建了四个ThreadTest对象,就等于创建了四个资源,每个资源都有100张票,每个线程都在独自处理各自的资源。
实现Runnable接口相对于继承Thread类来说,有如下显著的好处: 
    (1)适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。 
 
(2)可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。 
 
(3) 有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程操作相 同的数据,与它们的代码无关。当共享访问相同的对象是,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去, 这个对象就是一个实现了Runnable接口的类的实例。 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值