java线程基础知识总结

1.创建线程的方式

1.1继承Thread类并重写run方法

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

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

public class ThreadDemo2 {
	public static void main(String[] args) {
		//创建任务
		Runnable r1 = new MyRunnable1();
		Runnable r2 = new MyRunnable2();
		//创建线程
		Thread t1 = new Thread(r1);
		Thread t2 = new Thread(r2);
		t1.start();
		t2.start();
	}
}
class MyRunnable1 implements Runnable{
	public void run() {
		for (int i = 0; i <1000; i++) {
			System.out.println("你是谁");
		}	
	}
}
class MyRunnable2 implements Runnable{
	public void run() {
		for (int i = 0; i <1000; i++) {
			System.out.println("我是张三!");
		}	
	}
}

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

public class ThreadDemo3 {

	public static void main(String[] args) {
		Thread  t1 = new Thread() {;
		public void run() {
			for (int i = 0; i < 1000; i++) {
				System.out.println("你是谁");
			}
		}
		};
		
		Runnable r2 = ()->{
			for (int i = 0; i < 1000; i++) {
				System.out.println("我是张三!");
			}
		};
	
		Thread t2 = new Thread(r2);
		t1.start();
		t2.start();

	}
}

2.线程的优先级

/**
 * 线程的优先级
 * 
 * 线程获取CPU的时间片并发运行时,一切听从线程调度,线程是不能主动索取时间片的
 * 只能被动被分配。
 * 调整线程的优先级可以最大限度的干涉分配时间片的概率,原则上优先级越高的线程获取CPU时间片的次数越多。
 * @author 张庆裕
 *
 */
public class PriorityDemo {

	public static void main(String[] args) {
		Thread max = new Thread() {
			public void run() {
				for(int i=0;i<10000;i++) {
					System.out.println("max");
				}
			}
		};
		
		Thread norm = new Thread() {
			public void run() {
				for(int i=0;i<10000;i++) {
					System.out.println("nor");
				}
			}
		};
		
		Thread min = new Thread() {
			public void run() {
				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 张庆裕
 *
 */
public class SleepDemo {

	public static void main(String[] args) {
		System.out.println("程序开始了");
		/*
		 *实现一个倒计时程序,程序启动后要求输入一个整数,然后每秒递减,到0时输出时间到 
		 */
		Scanner scan = new Scanner(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 张庆裕
 *
 */
public class SleepDemo2 {

	public static void main(String[] args) {
		Thread lin = new Thread() {
			public void run() {
				System.out.println("林:我要睡觉了,别吵我!");
				try {
					Thread.sleep(100000);
				} catch (InterruptedException e) {
					System.out.println("林:干嘛嘞,干嘛嘞!");
					
				}
				System.out.println("林:我醒了");
			}
		};
		
		Thread huang = new Thread() {
			public void run() {
				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.线程的相关方法

public class ThreadInfoDemo {
	public static void main(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 张庆裕
 *
 */
public class DaemonThreadDemo {

    public static void main(String[] args) {
    Thread t1 = new MyCommon();
    Thread t2 = new Thread(new MyDaemon());
    t1.start();
    t2.setDaemon(true); //设置为守护线程,必须在该线程启动前进行!
    t2.start();
    }
}
class MyCommon extends Thread {
    public void run() {
        for (int i = 0; i < 5; i++) {
        System.out.println(Thread.currentThread().getName()+"线程1第" + i + "次执行!");
          try {
          Thread.sleep(7);
           } catch (InterruptedException e) {
                e.printStackTrace();
           }
        }
    }
}
class MyDaemon implements Runnable {
    public void run() {
       while (true){
           System.out.println(Thread.currentThread().getName()+"后台线程第次执行!");
           try {
              Thread.sleep(7);
           } catch (InterruptedException e) {
              e.printStackTrace();

            }

        }

    }
}

6.线程池

/**
 * 线程池
 * 线程池是管理线程的一套解决方案,主要工作:
 * 1:控制线程数量
 *   线程数量过多会消耗大量内存,有可能引起内存溢出崩溃,并且线程数量过多会导致CPU的过度切换,从而降低整体并发性能。
 * 2:重用线程
 *   线程不应当与任务的生命周期一致,重复使用线程可以减少线程调度器的不必要开销。
 * @author 张庆裕
 *
 */
public class ThreadPoolDemo {
	public static void main(String[] args) {
		ExecutorService threadPool = Executors.newFixedThreadPool(2);
		for(int i=0;i<5;i++) {
			Runnable r = new Runnable() {
				public void run() {
					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 张庆裕
 *
 */
public class SyncDemo1 {

	public static void main(String[] args) {
		Table beans = new Table();
		Thread t1 = new Thread() {
			public void run() {
				while(true) {
					int bean = beans.getBean();
					Thread.yield();
					System.out.println(getName()+":"+bean);
				}

			}
		};
		
		Thread t2 = new Thread() {
			public void run() {
				while(true) {
					int bean = beans.getBean();
					Thread.yield();
					System.out.println(getName()+":"+bean);
				}

			}
		};
		
		t1.start();
		t2.start();

	}
}
class Table{
	private int beans = 20;
	/**
	 * 当一个方法被synchronized修饰后,该方法称为同步方法,即:多个线程不能同时在方法
	 * 内部执行,将异步调用方法该为同步调用可以解决并发安全问题
	 * @return
	 */
	public synchronized int getBean(){ 
		if(beans==0) {
			throw new RuntimeException("没有豆子了!");
		}
		Thread.yield();//使当前线程由执行状态,变成为就绪状态,让出cpu时间,在下一个线程执行时候,此线程有可能被执行,也有可能没有被执行
		return beans--;
	}
}

7.2同步块

/**
 * 同步块:
 * 语法:
 * synchronized(同步监视器对象){
 * 需要多线程同步运行的代码片段
 * }
 * 
 * 同步块可以更准确的锁定需要同步运行的代码片段,有效的缩小同步范围可以在保证并发
 * 安全的前提下提高并发效率
 * @author 张庆裕
 *
 */
public class SyncDemo2 {

	public static void main(String[] args) {
		Shop shop = new Shop();
		Thread t1 = new Thread() {
			public void run() {
				shop.buy();
			}
		};
		
		Thread t2 = new Thread() {
			public void run() {
				shop.buy();
			}
		};
        t1.start();
        t2.start();
	}

}
class Shop{
	
	//public synchronized void buy() {//没有任何同步约束时性能最好,但是存在并发安全问题
	/*
	 * 在方法上使用synchronized,那么指定的同步对象监视器对象就是this
	 */
	public  void buy() {//解决了并发安全问题 ,但是性能不好,原因是衣服可同时挑,试衣同一时间只能一个人试衣服
		try {
			Thread t = Thread.currentThread();
			System.out.println(t.getName()+":正在挑衣服!");
			Thread.sleep(5000);
			/*
			 *同步块使用时要求必须指定同步监听器对象:()中的内容
			 *该对象可以是java中任何类型的实例。只需要保证一点:多个需要同步执行的线程看到的这个对象必须是同一个 
			 */
			synchronized(this) {//同对象同一时间只能有一个线程进入
				System.out.println(t.getName()+"正在试衣服!");
				Thread.sleep(5000);	
			}

			System.out.println(t.getName()+":结账离开!");
			
		} catch (Exception e) {

		}
	}
}

7.3静态方法修饰synchronized

/**
 * 成员方法上使用synchronized修饰后,锁对象为该方法所属对象this
 * 但是静态方法不同,箭头方法所属类,全局就一份,因为静态方法上使用synchronized后
 * 该方法一定具有同步效果,而它指定的锁对象为当前的类对象(Class的一个实例。)
 * @author 张庆裕
 *
 */
public class SyncDemo3 {

	public static void main(String[] args) {
		Boo b = new Boo();
		Thread t1 = new Thread() {
			public void run() {
				Boo.dosome();
			}
		};
		
		Thread t2 = new Thread() {
			public void run() {
				Boo.dosome();
			}
		};
		t1.start();
		t2.start();

	}
}
class Boo{
	public synchronized static void dosome() {
		try {
			synchronized (Boo.class) {
				Thread t = Thread.currentThread();
				System.out.println(t.getName()+":正在执行dosome方法");
				Thread.sleep(5000);
				System.out.println(t.getName()+"dosome方法执行完毕!");
			}
			
		} catch (Exception e) {
			
		}
	}
}

7.4互斥锁

/**
 * 互斥锁
 * 当使用多个synchronized锁定多个代码片段时,这些synchronized指定的同步监听器对象是同一个时,
 * 那么这些代码片段就是互斥的,多个线程不能同时执行写几个代码片段。
 * @author 张庆裕
 *
 */
public class SyncDemo4 {

	public static void main(String[] args) {
		Foo f = new Foo();
		Thread t1 = new Thread() {
			public void run() {
				f.methodA();
			}
		};
		
		Thread t2 = new Thread() {
			public void run() {

				f.methodB();
			}
		};
         t1.start();
         t2.start();
	}

}
class Foo{
	public synchronized void methodA() {
		/*
		 * 这样写仍然与下面的methodB方法有互斥效果,因为这里指定的同步监视器对象是this。
		 * 也就是nethodA方法所属对象,而methodB上直接写synchronized时指定的也是this
		 * 那么此时两个线程分别调用同一个Foo对象的methodA和methodB方法时就是互斥的
		 */
//		synchronized (this) {
//			
//		}
		try {
			Thread t = Thread.currentThread();
			System.out.println(t.getName()+":正在执行A方法...");
			Thread.sleep(5000);
			System.out.println(t.getName()+"A方法执行完毕!");
			
		} catch (Exception e) {
		}
	}
	
	public synchronized void methodB() {
		try {
			Thread t = Thread.currentThread();
			System.out.println(t.getName()+":正在执行B方法...");
			Thread.sleep(5000);
			System.out.println(t.getName()+"B方法执行完毕!");
			
		} catch (Exception e) {
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值