java线程基础知识总结

2022-08-03 11:09:46

1.创建线程的方式

1.1继承Thread类并重写run方法

publicclassThreadDemo1{publicstaticvoidmain(String[] args){
		MyThread1  t1=newMyThread1();
		MyThread2  t2=newMyThread2();/*
		 * 启动线程要调用start方法,而不是run方法
		 */
		t1.start();
		t2.start();}}/**
 * 第一种创建线程的方式的优点是定义简单,适合匿名内部类形式吃创建。
 * 缺点主要有两个:
 * 1:java是单继承的,这导致继承了Thread就无法再继承其他类去复用方法了,这在实际开发时很不方便。
 * 2:将任务定义在线程中,会导致线程和任务存在必然的耦合关系,不利于线程的重用
 * @author 张庆裕
 *
 */classMyThread1extendsThread{publicvoidrun(){for(int  i=0;i<100;i++){
			System.out.println("你是谁");}}}classMyThread2extendsThread{publicvoidrun(){for(int i=0;i<100;i++){
			System.out.println("我是张三");}}}

1.2实现Runnable接口单独定义线程任务

publicclassThreadDemo2{publicstaticvoidmain(String[] args){//创建任务
		Runnable r1=newMyRunnable1();
		Runnable r2=newMyRunnable2();//创建线程
		Thread t1=newThread(r1);
		Thread t2=newThread(r2);
		t1.start();
		t2.start();}}classMyRunnable1implementsRunnable{publicvoidrun(){for(int i=0; i<1000; i++){
			System.out.println("你是谁");}}}classMyRunnable2implementsRunnable{publicvoidrun(){for(int i=0; i<1000; i++){
			System.out.println("我是张三!");}}}

1.3使用匿名内部类形式创建线程

publicclassThreadDemo3{publicstaticvoidmain(String[] args){
		Thread  t1=newThread(){;publicvoidrun(){for(int i=0; i<1000; i++){
				System.out.println("你是谁");}}};
		
		Runnable r2=()->{for(int i=0; i<1000; i++){
				System.out.println("我是张三!");}};
	
		Thread t2=newThread(r2);
		t1.start();
		t2.start();}}

2.线程的优先级

/**
 * 线程的优先级
 * 
 * 线程获取CPU的时间片并发运行时,一切听从线程调度,线程是不能主动索取时间片的
 * 只能被动被分配。
 * 调整线程的优先级可以最大限度的干涉分配时间片的概率,原则上优先级越高的线程获取CPU时间片的次数越多。
 * @author 张庆裕
 *
 */publicclassPriorityDemo{publicstaticvoidmain(String[] args){
		Thread max=newThread(){publicvoidrun(){for(int i=0;i<10000;i++){
					System.out.println("max");}}};
		
		Thread norm=newThread(){publicvoidrun(){for(int i=0;i<10000;i++){
					System.out.println("nor");}}};
		
		Thread min=newThread(){publicvoidrun(){for(int i=0;i<10000;i++){
					System.out.println("min");}}};//线程优先级1最低,5默认,10最高
		max.setPriority(Thread.MAX_PRIORITY);
		norm.setPriority(Thread.NORM_PRIORITY);
		min.setPriority(Thread.MIN_PRIORITY);
		
		max.start();
		norm.start();
		min.start();}}

3.线程阻塞

3.1 Thread.Sleep(long ms)

/**
 * static void Sleep(long ms)
 * Thread提供的静态方法sleep可以让运行该方法的线程阻塞指定毫秒,超时后线程会自动
 * 回到RUNNABLE状态,等待再次获取时间片并发运行。
 * @author 张庆裕
 *
 */publicclassSleepDemo{publicstaticvoidmain(String[] args){
		System.out.println("程序开始了");/*
		 *实现一个倒计时程序,程序启动后要求输入一个整数,然后每秒递减,到0时输出时间到 
		 */
		Scanner scan=newScanner(System.in);
		System.out.println("请输入一个整数:");int num= scan.nextInt();while(num>0){try{
				System.out.println(num--);
				Thread.sleep(1000);}catch(InterruptedException e){// TODO Auto-generated catch block
				e.printStackTrace();}}
		System.out.println("时间到!");
		System.out.println("程序结束了");}}

3.2 interrupt()方法中断其sleep阻塞

/**
 * sleep方法要求我们必须处理InterruptedException,当一个线程调用sleep方法处于
 * 阻塞的过程中,此时该线程的interrupt()方法被调用时会中断其sleep阻塞,此时该方法就会抛出这个异常
 * @author 张庆裕
 *
 */publicclassSleepDemo2{publicstaticvoidmain(String[] args){
		Thread lin=newThread(){publicvoidrun(){
				System.out.println("林:我要睡觉了,别吵我!");try{
					Thread.sleep(100000);}catch(InterruptedException e){
					System.out.println("林:干嘛嘞,干嘛嘞!");}
				System.out.println("林:我醒了");}};
		
		Thread huang=newThread(){publicvoidrun(){
				System.out.println("黄:开始砸墙!");for(int i=0;i<5;i++){
					System.out.println("黄:80!");try{
						Thread.sleep(1000);}catch(InterruptedException e){}}
				System.out.println("黄:搞定了");
				lin.interrupt();}};
		lin.start();
		huang.start();}}

4.线程的相关方法

publicclassThreadInfoDemo{publicstaticvoidmain(String[] args){
		Thread t= Thread.currentThread();
		String name= t.getName();
		System.out.println("线程名字:"+name);long id= t.getId();
		System.out.println("唯一标识:"+id);int priority= t.getPriority();
		System.out.println("优先级:"+priority);//查看当前线程是否还活着boolean isAlive= t.isAlive();
		System.out.println("isAlive:"+isAlive);//查看线程是否为守护线程boolean isDaemon= t.isDaemon();
		System.out.println("isDaemon:"+isDaemon);//查看线程是否被中断了boolean isInterrupted= t.isInterrupted();
		System.out.println("isInterrupted:"+isInterrupted);}}

5.守护线程

/**
 * 守护线程
 * 守护线程是通过普通线程调用setDaemon方法设置而来的,因此创建和使用其实与普通
 * 线程无异。但是结束时机上有一点不同,即进程的结束
 *
 * 进程结束:当进程中的所有普通线程都结束时,进程就会结束,此时所有正在运行的守护线程都会被强制中断
 * @author 张庆裕
 *
 */publicclassDaemonThreadDemo{publicstaticvoidmain(String[] args){
    Thread t1=newMyCommon();
    Thread t2=newThread(newMyDaemon());
    t1.start();
    t2.setDaemon(true);//设置为守护线程,必须在该线程启动前进行!
    t2.start();}}classMyCommonextendsThread{publicvoidrun(){for(int i=0; i<5; i++){
        System.out.println(Thread.currentThread().getName()+"线程1第"+ i+"次执行!");try{
          Thread.sleep(7);}catch(InterruptedException e){
                e.printStackTrace();}}}}classMyDaemonimplementsRunnable{publicvoidrun(){while(true){
           System.out.println(Thread.currentThread().getName()+"后台线程第次执行!");try{
              Thread.sleep(7);}catch(InterruptedException e){
              e.printStackTrace();}}}}

6.线程池

/**
 * 线程池
 * 线程池是管理线程的一套解决方案,主要工作:
 * 1:控制线程数量
 *   线程数量过多会消耗大量内存,有可能引起内存溢出崩溃,并且线程数量过多会导致CPU的过度切换,从而降低整体并发性能。
 * 2:重用线程
 *   线程不应当与任务的生命周期一致,重复使用线程可以减少线程调度器的不必要开销。
 * @author 张庆裕
 *
 */publicclassThreadPoolDemo{publicstaticvoidmain(String[] args){
		ExecutorService threadPool= Executors.newFixedThreadPool(2);for(int i=0;i<5;i++){
			Runnable r=newRunnable(){publicvoidrun(){try{
						Thread t= Thread.currentThread();
						System.out.println(t.getName()+":正在执行任务...");
						Thread.sleep(5000);
						System.out.println(t.getName()+":执行任务完毕!");}catch(Exception e){}}};
			threadPool.execute(r);//将任务交给线程池
			System.out.println("指派了一个任务给线程池...");}//threadPool.shutdownNow();//调用该方法线程池处于STOP状态,此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务;
		System.out.println("停止线程池");}}

7.多线程并发安全问题

7.1.同步方法(synchronized)

/**
 * 多线程并发安全问题
 * 当多个线程并发操作同一临界资源时,由于线程切换的时机不确定,导致操作过程的顺序错乱,出现严重的后果
 * 临界资源:同时只能被单个线程操作的资源。
 * @author 张庆裕
 *
 */publicclassSyncDemo1{publicstaticvoidmain(String[] args){
		Table beans=newTable();
		Thread t1=newThread(){publicvoidrun(){while(true){int bean= beans.getBean();
					Thread.yield();
					System.out.println(getName()+":"+bean);}}};
		
		Thread t2=newThread(){publicvoidrun(){while(true){int bean= beans.getBean();
					Thread.yield();
					System.out.println(getName()+":"+bean);}}};
		
		t1.start();
		t2.start();}}classTable{privateint beans=20;/**
	 * 当一个方法被synchronized修饰后,该方法称为同步方法,即:多个线程不能同时在方法
	 * 内部执行,将异步调用方法该为同步调用可以解决并发安全问题
	 * @return
	 */publicsynchronizedintgetBean(){if(beans==0){thrownewRuntimeException("没有豆子了!");}
		Thread.yield();//使当前线程由执行状态,变成为就绪状态,让出cpu时间,在下一个线程执行时候,此线程有可能被执行,也有可能没有被执行return beans--;}}

7.2同步块

/**
 * 同步块:
 * 语法:
 * synchronized(同步监视器对象){
 * 需要多线程同步运行的代码片段
 * }
 * 
 * 同步块可以更准确的锁定需要同步运行的代码片段,有效的缩小同步范围可以在保证并发
 * 安全的前提下提高并发效率
 * @author 张庆裕
 *
 */publicclassSyncDemo2{publicstaticvoidmain(String[] args){
		Shop shop=newShop();
		Thread t1=newThread(){publicvoidrun(){
				shop.buy();}};
		
		Thread t2=newThread(){publicvoidrun(){
				shop.buy();}};
        t1.start();
        t2.start();}}classShop{//public synchronized void buy() {//没有任何同步约束时性能最好,但是存在并发安全问题/*
	 * 在方法上使用synchronized,那么指定的同步对象监视器对象就是this
	 */publicvoidbuy(){//解决了并发安全问题 ,但是性能不好,原因是衣服可同时挑,试衣同一时间只能一个人试衣服try{
			Thread t= Thread.currentThread();
			System.out.println(t.getName()+":正在挑衣服!");
			Thread.sleep(5000);
  • 作者:纵有千千星晚
  • 原文链接:https://blog.csdn.net/weixin_44980116/article/details/114363150
    更新时间:2022-08-03 11:09:46