线程(多线程、Thread、线程创建、线程池)(JAVA小白进阶day13)

线程

♥线程是进程的一部分,是进程的最小执行单位
1>程序:静态的代码
2>进程:程序动态的执行过程
3>线程:进程内最小的执行单位,是动态的执行过程
进程有自己独立的内存
线程共享进程的资源,在进程内,每个线程可以完成独立的功能
多线程效率高–tomcat服务器

1、创建线程两种方式

extends Thread:是线程
implements Runnable:不是线程,可实现线程

代码须写入线程体run()方法中
启动线程:start()方法

public class MyThread extends Thread{
	
	//主线程
	public static void main(String[] args) {
		T t1 = new T();
		T2 t2 = new T2();
		t1.start();
		t2.start();
	}
}
class T extends Thread {
	//线程完成功能代码需要写到线程体方法中run()方法
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println("hello");
		}
	}
}
class T2 extends Thread {
	//线程完成功能代码需要写到线程体方法中run()方法
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println("Thread");
		}
	}
}
//执行结果证明线程没有执行先后顺序,多线程抢占资源
class Runnable1 implements Runnable{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i <= 10; i++) {
			System.out.println(i);
		}
	}
}
public class Demo {
	public static void main(String[] args) {
		Runnable1 r = new Runnable1();
		Thread t = new Thread(r);
		t.start();
		Thread t2 = new Thread(
				()->{
					for (int i = 0; i <= 10; i++) {
						System.out.println("hello");
					}
				}
				);
		t2.start();
	}
}

练习1:用两种方法创建线程,一个打印奇数一个打印偶数(10以内的)

class Thread2 extends Thread{
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			if (i%2 == 0) {
				System.out.println(i);
			}
		}
	}
}
class Runnable3 implements Runnable{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 10; i++) {
			if (i%2 != 0) {
				System.out.println(i);
			}
		}
	}
}
public class Demo1 {
	public static void main(String[] args) {
		Thread2 t2 = new Thread2();
		t2.start();
		Runnable3 r3 = new Runnable3();
		Thread t3 = new Thread(r3);
		t3.start();
	}
}

2、常用方法

	//获取正在运行thread
	Thread t = Thread.currentThread();
	System.out.println(t);//Thread[Thread-0,5,main]线程优先级5,在main方法中
	//获取当前线程名
	System.out.println(t.getName());
	//获取当前线程ID
	System.out.println(t.getId());
	//查看线程可否使用	
	System.out.println(t.isAlive());//可用否
	//Sleep方法:线程休眠方法
	Thread.sleep(1000);
	//join方法:等待线程执行完毕

3、守护线程
setDeamon(true);
创建出来的线程:用户线程(前台线程)和守护线程(后台线程),默认用户线程
设置守护线程调用方法setDeamon(true)
用法和创建方式没有区别
区别:用户线程执行完毕,守护线程无条件停止执行

public class Demo6 {
	public static void main(String[] args) {
		Thread roseThread = new Thread() {
			public void run() {
				for (int i = 0; i <= 3; i++) {
					System.out.println("一起跳");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				System.out.println("扑通。。。");
			}
		};
		Thread jeckThread = new Thread(
				()->{
					while (true) {
						System.out.println("你先跳,我再跳");
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
		});
		roseThread.start();
		jeckThread.setDaemon(true);//在启动线程之前设置线程为守护线程
		jeckThread.start();
	}
}

4、线程的生命周期

新建状态:new Thread()
就绪状态:start()
阻塞状态:sleep(),wait(),io
运行状态:run()
消亡:执行完run()方法的语句

5、线程的优先级
不同优先级:高优先级先执行,低优先级后执行
同一优先级:先到先服务

public class Demo7 {
	public static void main(String[] args) {
		Thread t1 = new Thread(
				()->{
					for (int i = 0; i <= 10 ; i++) {
						System.out.println("t1");
					}
				}) ;
		Thread t2 = new Thread(
				()->{
					for (int i = 0; i <= 10 ; i++) {
						System.out.println("t2");
					}
				}) ;
		Thread t3 = new Thread(
				()->{
					for (int i = 0; i <= 10 ; i++) {
						System.out.println("t3");
					}
				}) ;
		t3.setPriority(Thread.MAX_PRIORITY);
		t1.setPriority(Thread.MIN_PRIORITY);
		t2.setPriority(Thread.NORM_PRIORITY);
		t1.start();
		t2.start();
		t3.start();
	}
}

6、线程的调度

7、线程的同步

多个线程来操作一个共享变量时,可能会导致共享变量的不完整(不安全)
为了保证共享变量的安全,使用同步机制保证共享变量的安全性
同步机制:当一个线程去改变共享变量值的时候,其它线程不能使用共享变量,当线程计算完成时,返回变量值之后,其它线程才可以使用共享变量
使用synchronized关键字实现线程同步
同步块synchronized
synchronized(锁对象){
共享变量相关的业务代码(运算)
}
在方法上synchronized,用词关键字修饰的方法叫同步方法

public class Demo8 {
	static int ticket = 10;
	public static void main(String[] args) {
		TicketThread tk = new TicketThread();
		TicketThread tk1 = new TicketThread();
		tk.start();
		tk1.start();
	}
}
class TicketThread extends Thread{
	static int ticket;
	public void run() {
		while(true) {
			synchronized (Demo8.class) {
				if (Demo8.ticket <= 0) {
					System.out.println("票卖完了");
					break;
				}
				else {
					Demo8.ticket--;
					System.out.println(Thread.currentThread().getName()+" 卖了1张票,还剩  "+Demo8.ticket+"张");
				}
			}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
}

public class Demo9 {
	public static void main(String[] args) {
		Shopping s = new Shopping();
		Thread t1 = new Thread(()-> {
			s.test();
		});
		Thread t2 = new Thread(()-> {
			s.test();
		});
		t1.start();
		t2.start();
	}
}
class Shopping{
	
	public void test() {
		System.out.println(Thread.currentThread().getName()+"选衣服");;
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		synchronized (this) {
			System.out.println(Thread.currentThread().getName()+"试衣服");
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

8、同比线程之间的通信
wait();
notify();
notifyAll();
使用两个线程交替打印10个数

class NumThread implements Runnable{
	int i = 1;
	@Override
	public void run() {
		synchronized (this) {
			while (i<=10) {
				notify();//唤醒
				System.out.println(Thread.currentThread().getName()+":"+i);
				i++;
				try {
					if(i>10) {break;}//if(i<11)  wait();
					else {
						
					}wait();//使当前线程处于等在状态
					
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
}
public class Demo1 {
	public static void main(String[] args) {
		NumThread num = new NumThread();
		new Thread(num).start();
		new Thread(num).start();
	}
}

======================================================

sleep()和wait()区别

1、sleep线程类的方法,wait是Object类的方法
2、sleep方法不是释放锁 ,wait是释放锁
3、sleep方法自动醒,wait必须通过使用notify,notifyAll唤醒

======================================================
1、线程的死锁
2、线程池
1>为什么使用线程池

频繁的创建线程,需要消耗时间和内存

2>使用线程池的好处

管理线程
使线程重用

3>创建线程池

newCacheThreadPool() //可创建多个线程
newFixedThreadPool(3) //创建3个线程♥常用♥♥
newScheduledThreadPool(5)
//excute(Runnable的子类,1,5,TimeUnit,SECONDS)
//多个参数可延迟启动,间隔5seconds
newSingleThreadPool() //创建单个线程池

4>关闭线程池

shutdown() //不关闭正在执行的线程
shutdownNow() //不管是否执行完毕都关闭

猜你喜欢

转载自blog.csdn.net/hyj_123/article/details/107706060