线程的基础知识梳理

1、线程与进程的:

  1. 进程:
    • 运行中的应用程序,没有运行的程序不算进程
    • 进程是Cpu分配资源的最小单位。
    • 单核的CPU任何时间点上都只能运行一个进程
  2. 线程
    • 轻量级的进程
    • 程序中的一个控制流程,也是CPU的基本调度单位
    • 进程可以由单个或者多个线程组成,彼此间完成不同的工作,交替执行,称为多线程
    • JVM虚拟机是一个进程,默认的包含主线程(main函数),可以通过代码创建多个独立的线程,与main线程并发执行
  3. 线程的组成:
    • 时间片,由Cpu分配的执行时间
    • 运行的数据
      • 堆空间:存储线程需要使用的对象,多个线程可以共享堆中的对象
      • 栈空间:存储线程需要使用局部变量,每个线程都拥有独立的栈、
  4. 多线程:
    • 宏观并行,微观串行

2、自定义线程

需要继承Thread或者实现Runnable

  1. 线程的创建

    • 继承Thread类
    • 实现Runnable接口
    • 他们都需要重写run方法。run方法里面就是调用该线程时需要完成的功能
  2. 两种方法的区别

    • 第一种方法,可以直接进行对线程的操作,即new出来的对象就是一个线程、代码相比较简单一些,但是只适用于单继承。
    • 第二种方法, new出的对象还不是线程,需要创建一个线程,然后把这个对象作为参数创建线程。
    • 第二种实现接口的方法,能够实现对象资源的共享
    class Test extends Thread {
        public void run(){
            System.out.println("线程名:" + Thread.curreantThread().getName());
        }
        public static void main(String[] args){
    		Test t = new Test();
            t.start();
        }
    }  
    
  3. 线程的命名:

    • 对于继承Thread类的线程,可以在构造方法中,调用父类的构造方法,传入线程名。

    • 对于实现Runnable接口的类,因为接口中没有构造方法,因此不能使用上面的方法,但是可以在声明线程的时候,加上线程名。

    • 他们都能调用setName()方法改变线程名

      public class Test extends Thread{
      	private String name ;
      	public Test(String name) {
      		super(name);
      	}
      	public void run() {
      		System.out.println(Thread.currentThread().getName());
      	}
      	public static void main(String[] args) {
      		Test t1 = new Test("线程A");
      		Test2 test2  = new Test2();
      		Thread t2 = new Thread(test2 , "线程B") ;
      //		t1.start();
      		t2.start();
      		
      		t1.setName("改变");
      		t1.start();
      	}
      }
      
      class Test2 implements Runnable{
      	public void run() {
      		System.out.println(Thread.currentThread().getName());
      	}
      }
      
  4. 调用start()方法与直接调用run()方法的区别

    • 调用start()方法,代表了启动一个线程
    • 直接调用run()方法,代表的只是单独的调用了run()方法;
  5. 线程的优先级Priority

    • 分为10级1~10,数字越大级别越高,但是优先级知识代表了获得时间片的概率。
    • getPriority()获得该线程的优先级
    • setPriority()改变线程的优先级
  6. 线程的常用方法

    • void setName(String name) 更改线程的名字
    • void setPriority(int newPriority) 更改线程的优先级
    • static void sleep(long millis) 线程进入睡眠状态millis时间
    • void join() 插队,谁调用它,谁先执行
    • static void yield() 礼让,主动的放弃时间片,回到就绪状态,竞争下一次的时间片,可能会继续抢到时间片。
    • void interrupt() 中断,只是添加一个中断标记,不会立刻停止
    • boolean isAlive() 判断线程是否死亡,以弃用
  7. 线程的状态

    • 初始状态:线程对象被创建,只在堆空间中开辟了内存,与常规的对象一样
    • 就绪状态:调用start()方法,进入就绪状态,等待os选中,并且分配时间片
    • 运行状态:获得时间片之后,进入运行状态,如果时间片到期,则回到就绪状态。
    • 终止状态:主线程或者独立的线程结束,进入终止状态,并且释放所有的时间片
    • 阻塞状态:就是其他的线程抢到了同步锁的控制权,其他线程进入阻塞状态。
  8. 线程的同步

    • 每一个线程,就拥有一个独立的run方法,因此当一个run方法被return终止的时候,不会因此结束别的线程。

    • 关键字synchronized 有两个适用场景

      • 对代码块进行加锁
      • 对方法进行加锁
    • synchronized关键字, ),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。

    • 当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定

      public class RunThread implements Runnable{
      	int length = 1000 ;
      	public void run() {
      		for(int i = 0 ; i <= 1000 ; i += 100) {
      			if(length == 0 ) {
      				break;
      			}
      			synchronized (this) {
      				for(int j = 0 ; j <= 100 ; j += 10) {
      					try {
      						Thread.sleep(100);
      					} catch (InterruptedException e) {
      						e.printStackTrace();
      					}
                       System.out.println(Thread.currentThread().getName() + "跑了十米");
      				}
      				length = length - 100 ;
      				System.out.println(Thread.currentThread().getName() + "跑了一百米 ,换下一人");
      				System.out.println("还剩下:" + (length) +"米");
      				return ;
      			}
      		}
      public class Test {
      	public static void main(String[] args) {
      		RunThread r = new RunThread();
      		
      		Thread t1 = new Thread(r,"1号" );
      		Thread t2 = new Thread(r,"2号" );
      		Thread t3 = new Thread(r,"3号" );
      		Thread t4 = new Thread(r,"4号" );
      		Thread t5 = new Thread(r,"5号" );
      		Thread t6 = new Thread(r,"6号" );
      		Thread t7 = new Thread(r,"7号" );  
      		Thread t8 = new Thread(r,"8号" );
      		Thread t9 = new Thread(r,"9号" );
      		Thread t10 = new Thread(r,"10号" );
      		
      		t1.start();
      		t2.start();
      		t3.start();
      		t4.start();
      		t5.start();
      		t6.start();
      		t7.start();
      		t8.start();
      		t9.start();
      		t10.start();
      	}
      }
      

3、生产者,消费者的问题

主要涉及到是两个Object之中的方法:

void wite(); 使线程进入等待的状态,直到线程被唤醒

void notfiy(); 唤醒线程 ,是随机唤醒

public class Com {
	private String host ;//主机
	private String display ;// 显示器
	List<Com> list = new ArrayList<Com>();
	public String getHost() {
		return host;
	}
	public void setHost(String host) {
		this.host = host;
	}
	public String getDisplay() {
		return display;
	}
	public void setDisplay(String display) {
		this.display = display;
	}
	
	public Com(String host , String display) {
		this.host = host ;
		this.display = display ;
	}
	public Com () {}

	public String toString() {
		return "这个电脑是:[主机是:" + host + "=== 显示器是:" + display  + "]";
	}
}

public class Consumer implements Runnable{
	private Com com = null ;
	public Com getCom() {
		return com;
	}
	public Consumer(Com com) {
		this.com = com;
	}
	public void run() {
		for(int i = 0 ; i <= 100 ; i++) {
			synchronized(com) {
				if(com.list.size() <= 0 ) {
					com.notify();
					try {
						com.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}else {
					for(int j = 4 ; j >= 0 ; j--)
					System.out.println(com.list.remove(j));
				}
			}
		}
	}
}

public class Pro implements Runnable{
	private Com com = null ;

	public Com getCom() {
		return com;
	}
	public Pro(Com com) {
		this.com = com;
	}
	public void run() {ynchronized (com) {
				for(int i = 1 ; i <= 100; i++) {
				if(com.list.size() >= 5) {
					com.notify();
					try {
						com.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}else {
					if (i % 2 == 0) {
						com.list.add(new Com("华硕" + i,"联想" + i + "号"));
					}else {
						com.list.add(new Com("泰坦" + i,"泰泰" + i + "号"));
					}
				}
			}
		}
	}
}

public class Supermarket {
	public static void main(String[] args) {
		Com com = new Com() ;
		Pro pro = new Pro(com);
		Consumer con = new Consumer(com);
		
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(con);
		
		t1.start();
		t2.start();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值