zoukankan      html  css  js  c++  java
  • Java-多线程(上)

    进程与线程的概念

    进程:操作系统中一个程序的执行周期称为一个进程。

    DOS系统的时代,由于其本身就是一个单进程的操作系统,所以在同一时间段上只能够有一个程序执行。后来发展到winodws系统后,我们发现多个程序可以同时执行,所以windows是一个多进程的操作系统。

    线程:一个程序同时执行多个任务。通常,每一个任务就称为一个线程。与进程相比较,线程更"轻量级",创建、撤销一个线程比启动一个新进程开销要小的多。没有进程就没有线程,进程一旦终止,其内的线程也将不复存在。

    多进程与多线程区别:本质区别在于,每个进程拥有自己的一整套变量,而线程则共享数据。共享变量使得线程之
    间的通信比进程之间通信更有效、更方便。

    那么,多线程表现在哪里呢?

    在实际应用中,多线程非常有用。例如,一个浏览器应用可以同时下载多个图片、音乐;一个Web服务器需要同时处理多个并发的请求。这些都是多线程的应用。

    高并发:访问的线程量非常非常高。

    高并发带来的问题:服务器内存不够用,无法处理新的请求。


    Java多线程实现

    方法1:继承Thread类实现多线程

    范例:

    class MyThread extends Thread { // 线程主体类
    	private String title;
    
    	public MyThread(String title) {
    		this.title = title;
    	}
    
    	@Override
    	public void run() { // 所有线程从此处开始执行
    		for (int i = 0; i < 10; i++) {
    			System.out.println(this.title + ",i = " + i);
    		}
    	}
    }

    正确启动多线程使用start()方法而不是run()!!!

    MyThread myThread1 = new MyThread("thread1") ;

    myThread1.start();

     

    方法2Runnable接口实现多线程

    Thread类的核心功能是进行线程的启动。如果一个类为了实现多线程直接去继承Thread类就会有但继承局限。在java中又提供有另外一种实现模式:Runnable接口。

    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }

    范例:

    class MyThread implements Runnable { // 线程主体类
    	private String title;
    
    	public MyThread(String title) {
    		this.title = title;
    	}
    
    	@Override
    	public void run() { // 所有线程从此处开始执行
    		for (int i = 0; i < 10; i++) {
    			System.out.println(this.title + ",i = " + i);
    		}
    	}
    }

    范例:使用匿名内部类进行Runnable对象创建

    public class TestDemo {
    	public static void main(String[] args) {
    		new Thread(new Runnable() {
    			@Override
    			public void run() {
    				System.out.println("Hello World");
    			}
    		}).start();
    	}
    }

    范例:使用Lamdba表达式进行Runnable对象创建

    public class TestDemo {
    	public static void main(String[] args) {
    		Runnable runnable = () -> System.out.println("Hello World");
    		new Thread(runnable).start();
    	}
    }

    ThreadRunnable区别


    范例:使用Thread实现数据共享(产生若干线程进行同一数据的处理操作)

    class MyThread extends Thread {
    	private int ticket = 10; // 一共10张票
    
    	@Override
    	public void run() {
    		while (this.ticket > 0) {
    			System.out.println("剩余票数:" + this.ticket--);
    		}
    	}
    }
    
    public class TestDemo {
    	public static void main(String[] args) {
    		new MyThread().start();
    		new MyThread().start();
    		new MyThread().start();
    	}
    }

    此时启动三个线程实现卖票处理。结果变为了卖各自的票。

    范例:使用Runnable实现共享

    class MyThread implements Runnable {
    	private int ticket = 10; // 一共10张票
    
    	@Override
    	public void run() {
    		while (this.ticket > 0) {
    			System.out.println("剩余票数:" + this.ticket--);
    		}
    	}
    }
    
    public class TestDemo {
    	public static void main(String[] args) {
    		MyThread mt = new MyThread();
    		new Thread(mt).start();
    		new Thread(mt).start();
    	}
    }

    Runnable实现的多线程的程序类可以更好的描述出程序共享的概念。


    方法3Callable实现多线程:

    @FunctionalInterface
    public interface Callable<V> {
    V call() throws Exception;
    }

            Runnable中的run()方法没有返回值,它的设计也遵循了主方法的设计原则:线程开始了就别回头。但是很多时候需要一些返回值,例如某些线程执行完成后可能带来一些返回结果,这种情况下就只能利用Callable来实现多线程。

    class MyThread implements Callable<String> {
    	private int ticket = 10; // 一共10张票
    
    	@Override
    	public String call() throws Exception {
    		while (this.ticket > 0) {
    			System.out.println("剩余票数:" + this.ticket--);
    		}
    		return "票卖完了,下次吧。。。";
    	}
    }
    
    public class TestDemo {
    	public static void main(String[] args) throws InterruptedException, ExecutionException {
    		FutureTask<String> task = new FutureTask<>(new MyThread());
    		new Thread(task).start();
    		new Thread(task).start();
    		System.out.println(task.get());
    	}
    }

    Thread类中提供有如下的线程名称方法:

     

    获取当前线程名字方式:Thread.currentThread().getName();

    通过以上程序我们发现,主方法本身就是一个线程,所有的线程都是通过主线程创建并启的。

    疑问:进程在哪?

    实际上每当使用了java命令去解释程序的时候,都表示启动了一个新的JVM进程。而主方法只是这个进程上的一个线程而已。


    线程的五种状态之间的相互转换


    线程休眠(sleep方法)

    线程休眠:指的是让线程暂缓执行一下,等到了预计时间之后再恢复执行。

     

    线程让步(yield()方法)

    暂停当前正在执行的线程对象,并执行其他线程。

    注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。

     

    join()方法(插队方法)

    等待该线程终止。意思就是如果在主线程中调用该方法时就会让主线程休眠,让调用该方法的线程run方法先执行完毕之后在开始执行主线程。

     

    线程停止

    多线程中有三种方式可以停止线程。

    1. 设置标记位,可以使线程正常退出。

    2. 使用stop方法强制使线程退出,但是该方法不太安全所以已经被废弃了。

    3. 使用Thread类中的一个 interrupt() 可以中断线程。

     

    线程优先级

    线程的优先级指的是,线程的优先级越高越有可能先执行,但仅仅是有可能而已。

    设置优先级 public final void setPriority(int newPriority)

    取得优先级 public final int getPriority()

    1. 最高优先级:public final static int MAX_PRIORITY = 10;

    2. 中等优先级:public final static int NORM_PRIORITY = 5;

    3. 最低优先级:public final static int MIN_PRIORITY = 1;

    线程是有继承关系的,比如当A线程中启动B线程,那么BA的优先级将是一样的。

  • 相关阅读:
    ini_set /ini_get函数功能-----PHP
    【转】那个什么都懂的家伙
    word 2007为不同页插入不同页眉页脚
    August 26th 2017 Week 34th Saturday
    【2017-11-08】Linux与openCV:opencv版本查看及库文件位置等
    August 25th 2017 Week 34th Friday
    August 24th 2017 Week 34th Thursday
    August 23rd 2017 Week 34th Wednesday
    August 22nd 2017 Week 34th Tuesday
    August 21st 2017 Week 34th Monday
  • 原文地址:https://www.cnblogs.com/yongtaochang/p/13615349.html
Copyright © 2011-2022 走看看