zoukankan      html  css  js  c++  java
  • java线程

    线程

    串行单线程执行

    在食堂打饭的时候,食堂安排一个打饭大妈打饭,所有同学都排成一个队形,打饭大妈相当于线程,同学打饭相当于任务,这种一个大妈给一群站好队形的同同学打饭相当于java中的单线程串行执行任务。

    串行执行的缺点很明显,当一个同学选菜慢的情况下,效率低下,后面的同学早已不耐烦了

    并行多线程执行

    为了解决上述问题,食堂打算聘请和学生数目一样多的打饭大妈,同时给同学打饭,这样的话同学倒是开心了,很快就能吃上饭,但是食堂承受不了了,因为食堂需要开更多的打饭窗口以及给大妈的工资,映射到多线程中也一样,如果每个任务都创建一个线程来处理的话,任务数量一旦多了,内存就会有很大的负担,甚至可能宕机。

    线程池

    为了解决上述问题,食堂又做了改进,就是先确定好打饭大妈的数量,然后让同学们排队,每个打饭大妈打完一次饭就叫队列中的下一个。映射到java中我们创建指定数量的线程,然后把任务放到一个队列中去处理,当每个线程处理完任务后就会去队列中取下一个任务处理,可以把线程重复利用,因为线程的创建也是消耗资源的。

    所以结论就是:在一定范围内增加线程数量的确可以提升系统的处理能力,但是过多的创建线程将会降低系统的处理速度,如果无限制的创建线程,将会使系统崩溃。


    对于一个程序,默认只有一个进程,按照一定的顺序进行操作
    但是,如果对一个事件操作很慢,但是cpu内存又足够大去对另一个事件操作
    就需要进行并事件操作,也就是多进程,同时操作不同的事件,节省了时间,使得cpu在同样的时间里完成更多的事件

    线程的实现

    线程实现有两种方法

    • 继承Thread类,重写run()方法
    • 实现Runnable接口,实现run()方法

    几个重要的函数

    Thread.currentThread().getName()获取当前线程的名字.
    对于线程的名字,如果没有去给他命名,系统自带为他命名
    start()
    启动一个线程

    继承Thread

    package Experiment;
    
    public class E13{
    	public static void main(String[] args) {
    		MyThread t1 = new MyThread();
    		t1.start();
    		
    		MyThread t2 = new MyThread();
    		t2.start();
    	}
    }
    class MyThread extends Thread{
    	public void run(){
    		for(int i=1;i<20;i++){
    			System.out.println(Thread.currentThread().getName()+"-->"+i);
    		}
    	}
    }
    

    输出

    Thread-0-->1
    Thread-1-->1
    Thread-0-->2
    Thread-1-->2
    Thread-0-->3
    Thread-1-->3
    Thread-1-->4
    Thread-1-->5
    Thread-0-->4
    Thread-1-->6
    Thread-1-->7
    Thread-0-->5
    Thread-1-->8
    Thread-1-->9
    Thread-0-->6
    Thread-1-->10
    Thread-0-->7
    Thread-1-->11
    Thread-0-->8
    Thread-1-->12
    Thread-0-->9
    Thread-1-->13
    Thread-0-->10
    Thread-1-->14
    Thread-0-->11
    Thread-1-->15
    Thread-0-->12
    Thread-1-->16
    Thread-0-->13
    Thread-1-->17
    Thread-1-->18
    Thread-0-->14
    Thread-1-->19
    Thread-0-->15
    Thread-1-->20
    Thread-0-->16
    Thread-0-->17
    Thread-0-->18
    Thread-0-->19
    Thread-0-->20
    

    可以发现有40条记录,线程0是e1线程,线程1是e2线程
    他们是同时进行操作的

    Runnable接口

    package Experiment;
    
    public class E13{
    	public static void main(String[] args) {		
    		Thread t3 = new Thread(new Task());
    		t3.start();
    		
    		Thread t4 = new Thread(new Task());
    		t4.start();
    	}
    }
    class Task implements Runnable{
    	public void run() {
    		for(int i=1;i<=20;i++) {
    				System.out.println(Thread.currentThread().getName()+"-->"+i);
    		}
    	}
    }
    

    输出

    Thread-1-->1
    Thread-0-->1
    Thread-1-->2
    Thread-0-->2
    Thread-1-->3
    Thread-0-->3
    Thread-1-->4
    Thread-0-->4
    Thread-1-->5
    Thread-0-->5
    Thread-1-->6
    Thread-0-->6
    Thread-1-->7
    Thread-0-->7
    Thread-1-->8
    Thread-0-->8
    Thread-1-->9
    Thread-0-->9
    Thread-1-->10
    Thread-0-->10
    Thread-1-->11
    Thread-0-->11
    Thread-1-->12
    Thread-0-->12
    Thread-1-->13
    Thread-0-->13
    Thread-0-->14
    Thread-0-->15
    Thread-0-->16
    Thread-1-->14
    Thread-1-->15
    Thread-1-->16
    Thread-1-->17
    Thread-1-->18
    Thread-1-->19
    Thread-1-->20
    Thread-0-->17
    Thread-0-->18
    Thread-0-->19
    Thread-0-->20
    

    发现Runnable接口和继承Thread的效果差不多

    区别

    ①由于Java不允许多继承,所以继承了Thread类,就不能继承其他类,而Runnable接口可以继续接其他接口
    ②实现Runnable接口的线程类的多个线程,适合访问同一变量,而Thread不能(多窗口买票问题)
    ③Thread采用了Runnable接口

    第②点的原因是两者的启动方式不同,Runnable线程类是实例化一个对象O后,多次进行new Thread(O).start(),对象,这几个线程属于同一个对象,对象的成员变量是同一个
    而对于Thread线程类启动多个线程需要new MyThread().start();每个线程启动都对应不同的对象,他们的成员变量是独立的
    而如果Thread加了synchronized之后也是可以访问同一个变量的
    所以,只是Thread不适合去访问同一个变量

    从Thread源码中也可以看到,当以Thread方式去实现资源共享时,实际上源码内部是将thread向下转型为了Runnable,实际上内部依然是以Runnable形式去实现的资源共享

    比如

    package Experiment;
    
    public class E13{
    	public static void main(String[] args) {
    	    MyThread t=new MyThread();//只能使用同一个t
    	    new Thread(t).start();
    	    new Thread(t).start();
    	    new Thread(t).start();
    	    new Thread(t).start();
    	}
    }
    
    class MyThread implements Runnable{
    	private int ticket=100;
    	@Override
    	public void run() {
    	    // TODO Auto-generated method stub
    	    while(true){
    	        if(ticket>0){
    	            System.out.println(Thread.currentThread().getName()+"...is saling,余票:"+ticket--);
    	        }
    	    }
    	}
    }
    

    输出

    Thread-0...is saling,余票:100
    Thread-2...is saling,余票:98
    Thread-2...is saling,余票:95
    Thread-1...is saling,余票:99
    Thread-2...is saling,余票:94
    Thread-0...is saling,余票:97
    Thread-3...is saling,余票:96
    Thread-0...is saling,余票:91
    Thread-2...is saling,余票:92
    Thread-1...is saling,余票:93
    Thread-2...is saling,余票:88
    Thread-2...is saling,余票:86
    Thread-2...is saling,余票:85
    Thread-0...is saling,余票:89
    Thread-3...is saling,余票:90
    Thread-0...is saling,余票:83
    Thread-2...is saling,余票:84
    Thread-1...is saling,余票:87
    Thread-2...is saling,余票:80
    Thread-0...is saling,余票:81
    Thread-3...is saling,余票:82
    Thread-0...is saling,余票:77
    Thread-2...is saling,余票:78
    Thread-1...is saling,余票:79
    Thread-2...is saling,余票:74
    Thread-0...is saling,余票:75
    Thread-3...is saling,余票:76
    Thread-0...is saling,余票:71
    Thread-2...is saling,余票:72
    Thread-1...is saling,余票:73
    Thread-2...is saling,余票:68
    Thread-0...is saling,余票:69
    Thread-3...is saling,余票:70
    Thread-0...is saling,余票:65
    Thread-2...is saling,余票:66
    Thread-1...is saling,余票:67
    Thread-2...is saling,余票:62
    Thread-2...is saling,余票:60
    Thread-0...is saling,余票:63
    Thread-3...is saling,余票:64
    Thread-3...is saling,余票:57
    Thread-0...is saling,余票:58
    Thread-2...is saling,余票:59
    Thread-1...is saling,余票:61
    Thread-2...is saling,余票:54
    Thread-0...is saling,余票:55
    Thread-3...is saling,余票:56
    Thread-0...is saling,余票:51
    Thread-2...is saling,余票:52
    Thread-1...is saling,余票:53
    Thread-2...is saling,余票:48
    Thread-0...is saling,余票:49
    Thread-3...is saling,余票:50
    Thread-0...is saling,余票:45
    Thread-2...is saling,余票:46
    Thread-1...is saling,余票:47
    Thread-2...is saling,余票:42
    Thread-0...is saling,余票:43
    Thread-3...is saling,余票:44
    Thread-0...is saling,余票:39
    Thread-2...is saling,余票:40
    Thread-1...is saling,余票:41
    Thread-2...is saling,余票:36
    Thread-0...is saling,余票:37
    Thread-3...is saling,余票:38
    Thread-0...is saling,余票:33
    Thread-2...is saling,余票:34
    Thread-1...is saling,余票:35
    Thread-2...is saling,余票:30
    Thread-0...is saling,余票:31
    Thread-3...is saling,余票:32
    Thread-0...is saling,余票:27
    Thread-2...is saling,余票:28
    Thread-1...is saling,余票:29
    Thread-2...is saling,余票:24
    Thread-0...is saling,余票:25
    Thread-3...is saling,余票:26
    Thread-0...is saling,余票:21
    Thread-2...is saling,余票:22
    Thread-1...is saling,余票:23
    Thread-2...is saling,余票:18
    Thread-0...is saling,余票:19
    Thread-0...is saling,余票:15
    Thread-3...is saling,余票:20
    Thread-0...is saling,余票:14
    Thread-2...is saling,余票:16
    Thread-1...is saling,余票:17
    Thread-2...is saling,余票:11
    Thread-0...is saling,余票:12
    Thread-3...is saling,余票:13
    Thread-0...is saling,余票:8
    Thread-2...is saling,余票:9
    Thread-1...is saling,余票:10
    Thread-2...is saling,余票:5
    Thread-0...is saling,余票:6
    Thread-3...is saling,余票:7
    Thread-3...is saling,余票:1
    Thread-0...is saling,余票:2
    Thread-2...is saling,余票:3
    Thread-1...is saling,余票:4
    

    可以发现这100条是一起操作的,没有重复

    而对于继承

    package Experiment;
    
    public class E13{
    	public static void main(String[] args) {
    	    MyThread t=new MyThread();//只能使用同一个t
    	    
    	    //10个线程
    	    new MyThread().start();
    	    new MyThread().start();
    	    new MyThread().start();
    	    new MyThread().start();
    	}
    }
    
    class MyThread extends Thread{
    	private int ticket=10;
    	@Override
    	public void run() {
    	    // TODO Auto-generated method stub
    	    while(true){
    	        if(ticket>0){
    	            System.out.println(Thread.currentThread().getName()+"...is saling,余票:"+ticket--);
    	        }
    	    }
    	}
    }
    

    输出

    Thread-2...is saling,余票:10
    Thread-3...is saling,余票:10
    Thread-1...is saling,余票:10
    Thread-1...is saling,余票:9
    Thread-4...is saling,余票:10
    Thread-3...is saling,余票:9
    Thread-2...is saling,余票:9
    Thread-3...is saling,余票:8
    Thread-4...is saling,余票:9
    Thread-1...is saling,余票:8
    Thread-4...is saling,余票:8
    Thread-3...is saling,余票:7
    Thread-2...is saling,余票:8
    Thread-3...is saling,余票:6
    Thread-4...is saling,余票:7
    Thread-1...is saling,余票:7
    Thread-4...is saling,余票:6
    Thread-3...is saling,余票:5
    Thread-2...is saling,余票:7
    Thread-3...is saling,余票:4
    Thread-4...is saling,余票:5
    Thread-1...is saling,余票:6
    Thread-4...is saling,余票:4
    Thread-3...is saling,余票:3
    Thread-2...is saling,余票:6
    Thread-3...is saling,余票:2
    Thread-4...is saling,余票:3
    Thread-1...is saling,余票:5
    Thread-4...is saling,余票:2
    Thread-4...is saling,余票:1
    Thread-3...is saling,余票:1
    Thread-2...is saling,余票:5
    Thread-2...is saling,余票:4
    Thread-2...is saling,余票:3
    Thread-2...is saling,余票:2
    Thread-2...is saling,余票:1
    Thread-1...is saling,余票:4
    Thread-1...is saling,余票:3
    Thread-1...is saling,余票:2
    Thread-1...is saling,余票:1
    

    每个线程是独立的
    只是在同一时间完成4个线程而已

    如果加了synchronized (this),那么两者都可以实现资源共享了

    但既然Thread是采用了Runnable接口,那么Thread有什么好处,为什么创建Thread ?

  • 相关阅读:
    web前端的发展态势
    AngularJs 简单入门
    css代码优化篇
    git提交报错:Please make sure you have the correct access rights and the repository exists.
    Activiti工作流框架学习
    遍历map集合的4种方法
    js设置日期、月份增加减少
    Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    webservice_rest接口_学习笔记
    相互匹配两个list集合+动态匹配${}参数
  • 原文地址:https://www.cnblogs.com/Emcikem/p/11892419.html
Copyright © 2011-2022 走看看