Thread(线程)

单线程和多线程

在这里插入图片描述
多线程的利弊:

  • 利:多线程可以提高程序运行效率和资源的利用率。
  • 弊:多线程会比较消耗资源,效率比较低。处理不好的话会造成线程死锁。

代码演示单线程和多线程



public class ThreadDemo extends Thread {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 5; i++) {

			try {
				sleep(1000);// 睡一秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			System.out.println(Thread.currentThread().getName() + "一共卖出了" + i + "张票");

		}
	}

	public static void main(String[] args) {
		ThreadDemo threadDemo1 = new ThreadDemo();
		ThreadDemo threadDemo2 = new ThreadDemo();
		 threadDemo1.setName("一号售卖机");
		 threadDemo2.setName("二号售卖机");
		/*
		 *  调用方法(单线程)
		 */
		threadDemo1.run();
		threadDemo2.run();
		
		/*
		 * start启动线程(多线程)
		 */
		threadDemo1.start();
		threadDemo2.start();
	}
}


多线程的实现方法

  1. 继承Thread类
    从Thread类中实例化的对象即代表线程,启动一个线程就是建立一个Thread实例。因为完成线程真正功能的代码放在类的run()方法中,所以可以将线程要做的事写在run()方法中即可。然后调用Thread类中的start()方法执行线程,也就是调用run()方法。

public class ThreadDemo extends Thread {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 5; i++) {

			try {
				sleep(1000);// 睡一秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			System.out.println(Thread.currentThread().getName() + "一共卖出了" + i + "张票");

		}
	}

	public static void main(String[] args) {
		ThreadDemo threadDemo1 = new ThreadDemo();
		ThreadDemo threadDemo2 = new ThreadDemo();
		threadDemo1.setName("一号售卖机");
		threadDemo2.setName("二号售卖机");
		/*
		 * start启动线程(多线程)
		 */
		threadDemo1.start();
		threadDemo2.start();
	}
}

  1. 实现Runnable接口(推荐使用)
    Java不支持多重继承(推荐的原因),因此如果有一个子类要想实现线程,那就可以实现Runnable接口。实现了Runnable接口并编写run()方法,使该任务可执行你的命令。

public class ThreadDemo2 implements Runnable {

	@Override
	public void run() {

		for (int j = 0; j < 5; j++) {
			try {
				Thread.currentThread().sleep(1000);

			} catch (InterruptedException e) {

				e.printStackTrace();

			}

			System.out.println(Thread.currentThread().getName() + "一共卖出了" + j + "张票");

		}

	}

	public static void main(String[] args) {

		ThreadDemo2 t1 = new ThreadDemo2();
		ThreadDemo2 t2 = new ThreadDemo2();

		Thread thread1 = new Thread(t1);
		Thread thread2 = new Thread(t2);

		thread1.setName("一号售卖机");
		thread2.setName("二号售卖机");
		
		thread1.start();
		thread2.start();

	}
}

  1. 实现Callable接口
    Callable接口类似于Runnable接口,实现起来较为复杂,和Runnable接口有些不同,最主要的区别是Callable接口要实现的call()方法中可以抛出异常,且还可以在任务执行后返回值。

多线程安全问题

俗话说:有利必有弊。
多线程提高程序运行效率和资源的利用率的同时也会遇到安全问题。
我们肯定要做到资源在同一时间只能有一个线程访问。

如何解决?

  1. 我们可以采用同步方法,用synchronized修饰方法,整个方法的代码都是同步的,只能一个线程运行。同步方法使用this作为锁。
synchronized(xxx.class){
中间是要同步的代码
}
  1. 同步锁
Lock lock =new ReentrantLock();
		lock.lock();
		try {
		/*
		 * 同步代码块
		 */
		} finally {
			lock.unlock();
		}

线程通信

在这里插入图片描述
使用锁对象的notify()方法可以将正在等待的线程唤醒,但是同时有多个线程都处于等待状态,notify()只是随机唤醒一个。

总结

  • 线程同步的目的是为了保护资源,防止多个线程访问同一个资源时破坏了资源。

  • 线程同步方法是通过锁来实现,每个对象都有且仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其它访问该对象的线程就无法再访问该对象的其他同步方法。

  • 对于同步,要时刻清楚在哪个对象上同步,这是关键。

  • 当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。

  • 使用lock()来代替synchronized时,一定要解锁并注意unlock()的位置

猜你喜欢

转载自blog.csdn.net/Mr_Qian_Ives/article/details/104339707