java多线程开发

本文详细介绍了进程和线程的区别,展示了如何在Java中通过继承Thread类或实现Runnable接口创建线程,实现在下载与播放任务中并行操作。还探讨了线程控制方法及暂停/继续策略,以及线程同步在并发下载文件中的应用。

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

线程与进程

进程(Process):操作系统中能够同时运行的多个软件(QQ、浏览器、Word、WPS),实际上在底层上是“分时”系统,如何分时?由操作系统决定
线程(Thread):一个应用程序中,能够同时运行的多个任务,比如:在线播放(一边下载、一边播放),实际上在底层上是“分时”系统,如何分时?由操作系统决定

很多软件都支持线程功能:QQ(用户一边接受信息,一边发送信息);抖音(一边下载,一边播放),针对Java语言,我们讲解线程;如果是讲解进程,在操作系统课中

线程

例子:对于某软件,需要一边下载,一边播放,怎么实现?
情景一:不用线程怎么做?

class Downloader{
    public void download()
    {
        for(int i=1;i<=10;i++)
        {
            System.out.println("下载进度:"+i*10+"%");
        }
    }
}

class Player{
    public void Play()
    {
        for(int i=1;i<=10;i++)
        {
            System.out.println("播放进度:"+i*10+"%");
        }
    }
}


public class TreadTest {
    public static void main(String[] args) {
        Downloader d=new Downloader();
        Player p=new Player();
        d.download();
        p.Play();
    }
}

实际考虑:

class Downloader{
    public void download()
    {
        for(int i=1;i<=10;i++)
        {
            try{Thread.sleep(1000);}catch(Exception ex){}
            System.out.println("下载进度:"+i*10+"%");
        }
    }
}

class Player{
    public void Play()
    {
        for(int i=1;i<=10;i++)
        {
            try{Thread.sleep(1000);}catch(Exception ex){}
            System.out.println("播放进度:"+i*10+"%");
        }
    }
}


public class TreadTest {
    public static void main(String[] args) {
        Downloader d=new Downloader();
        Player p=new Player();
        d.download();
        p.Play();
    }
}

情景2:如何用线程解决此问题?

实现线程的两种办法:
1. 让需要实现线程的类,继承Java.lang.Thread类;讲需要实现线程的代码,放在从Thread类中重写的run函数里面;开启线程,用线程对象的start方法
问题:用了多线程,多个任务完成的比以前快,是不是说明多线程让CPU运行的更快了呢?不是。只是让CPU的利用率提高了!

class Downloader extends Thread{//第一步:继承Thread
    public void run()//第二步:重写run函数
    {
        for(int i=1;i<=10;i++)
        {
            try{Thread.sleep(1000);}catch(Exception ex){}
            System.out.println("下载进度:"+i*10+"%");
        }
    }
}

class Player extends Thread{
    public void run()
    {
        for(int i=1;i<=10;i++)
        {
            try{Thread.sleep(1000);}catch(Exception ex){}
            System.out.println("播放进度:"+i*10+"%");
        }
    }
}


public class TreadTest {
    public static void main(String[] args) {
        Downloader d=new Downloader();
        Player p=new Player();
        d.start(); p.start();//用start方法
    }
}

2.让需要实现线程的类,实现Java.lang.Runnable接口;讲需要实现线程的代码,放在.Runnable接口重写的run函数里面;实例化线程,将类的对象传入线程呢个的构造函数,再调用线程的start方法

class Downloader implements Runnable{//第一步:接口Runnable
    public void run()//第二步:重写run函数
    {
        for(int i=1;i<=10;i++)
        {
            try{Thread.sleep(1000);}catch(Exception ex){}
            System.out.println("下载进度:"+i*10+"%");
        }
    }
}

class Player implements Runnable{
    public void run()
    {
        for(int i=1;i<=10;i++)
        {
            try{Thread.sleep(1000);}catch(Exception ex){}
            System.out.println("播放进度:"+i*10+"%");
        }
    }
}


public class TreadTest {
    public static void main(String[] args) {
        Downloader d=new Downloader();
        Thread th1=new Thread(d);
        Player p=new Player();
        Thread th2=new Thread(p);
        th1.start(); th2.start();//第三步:实例化线程,将类的对象传入线程的构造函数,再调用线程的start方法
    }
}

额外内容:

线程控制(线程开启、暂停、继续、结束)

线程开启:start
线程暂停:suspend
线程继续:resume
线程结束:run函数运行完毕
例5:下载文件,下载到30%,暂停下载5秒,5秒后继续下载

class Downloader extends Thread{ 
	public void run() {	
		for(int i=1;i<=10;i++){
			try{  Thread.sleep(1000);  } catch(Exception ex){}  
			System.out.println("下载进度:"+i*10+"%");
		}		
	}
}
class ThreadTest{
	public static void main (String[] args) throws Exception {
		Downloader d = new Downloader();
		d.start();	
		Thread.sleep(3200);
		d.suspend();
		Thread.sleep(5000);
		d.resume();
	}
}

注意:suspend、resume是不建议使用的函数,有死锁倾向

这两个函数,特别是suspend,在暂停时不会释放线程中的资源,导致资源被该线程长期持有,别人不能使用。可能造成循环等待。【死锁的概念,详见操作系统课程】所以不建议使用。

怎么办?线程暂停,就让该线程结束(run函数运行完毕);线程继续,新开启一个线程(start)

改进:

class Downloader extends Thread{ 
    boolean RUN = true;
    static int i = 1;
	public void run() {	
		for(;i<=10&&RUN;i++){
			try{  Thread.sleep(1000);  } catch(Exception ex){}  
			System.out.println("播放进度:"+i*10+"%");
		}		
	}
}
class ThreadTest{
	public static void main (String[] args) throws Exception {
		Downloader d = new Downloader();
		d.start();	
		Thread.sleep(3000);
		d.RUN = false;
		Thread.sleep(5000);
		d = new Downloader();
		d.start();
	}
}

线程同步:主要出现在“多个线程访问同一内存资源的场合”

例子:下载文件时,如果同时开多个线程下载文件,可以提高下载速度
举例:两个线程,下载文件。
解决同步问题:用synchronized将原子代码包含起来,保证其要么全部运行,要么全部不运行,别的线程在此之间,无法抢占CPU

class Downloader implements Runnable{ 
    static int i = 1;
	public void run() {	
		while(true){
			synchronized(this){
				if(i>10)  {	break; }
				try{  Thread.sleep(1000);  } catch(Exception ex){}  
				System.out.println("下载进度:"+i*10+"%");
				i++;
			}			
		}		
	}
}
class ThreadTest{
	public static void main (String[] args) throws Exception {
		Downloader d = new Downloader();
		new Thread(d).start();  new Thread(d).start();
	}
}

这种方式,实际上是将线程功能进行了退化,“几乎又变成串行了!”
实际过程中,如何解决此问题呢?方法是:人为进行资源划分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值