欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多线程笔记 多学多练(一)

程序员文章站 2022-03-08 18:58:52
...

                                  java多线程学习笔记 

  写在前言,不管学习什么知识点,自己还是要边学边用。

  在学习的过程中把一些自己认为重要的知识点记下来,看书只是为了看明白,吸收为自己的东西还需要自己多练练。然后自己做个总结,隔一段时间翻翻看看,这样长期有效记忆会很深刻。

 多线程的书籍有很多,但是通俗易懂,结构层次清晰的我还是推荐一本书《java多线程编程核心技术》

好了,言归正传。我们来一起学习多线程吧。   

 

1、 进程和线程的概念

 什么是进程呢? 

进程就是一个程序运行中所占用一定的资源,进程是程序的实体。

什么又是线程呢?

线程就是进程里独立运行的子程序,比如音乐播放器边播放音乐,边去下载音乐。这就是2个子程序同时进行的。、

那用多线程有什么好处吗?

使用多线程,可以充分利用CPU资源。现在多核CPU很常见,一个程序的多个线程在不同时间在CPU不同核中进行处理,而不用等一个任务执行完后再执行下一个任务,这样效率太低了。但是多个线程在不同核中不停地切换,就需要消耗一定的时间资源。

 Java多线程笔记 多学多练(一)

 

2、如何使用多线程 

java使用多线程有两种方法:

1)继承Thread类

其实,Thread类也是实现了Runnabled的接口

public class Thread implements Runnable {}
public class ThreadDemo extends Thread{}

 

2)实现Runnabled接口

public class ThreadDemo implements Runnable {

      @Override
	public void run() {
		
	}

}

我们来看看下面的一段代码:

public class ThreadDemo extends Thread {
	private int i = 0;
	
	@Override
	 public void run() {
		i++;
		System.out.println("i:" + i);
	}

	public static void main(String[] args0) {
		ThreadDemo threadDemo = new ThreadDemo();
		Thread t = new Thread(threadDemo);
		Thread t2 = new Thread(threadDemo);
		Thread t3 = new Thread(threadDemo);
		Thread t4 = new Thread(threadDemo);
		Thread t5 = new Thread(threadDemo);
		t.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		//System.out.println("run over.");
	}
}

结果是:

Java多线程笔记 多学多练(一)

可以看出线程是乱序执行的,如果想让它按照顺序执行,这样的程序是线程不安全的。也就是数据共享,没有原子性。其他线程容易篡改变量的值,造成了脏读、幻读的影响,将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 从而保证了该变量的唯一性和准确性就使用 synchronized关键字。

Java多线程笔记 多学多练(一)

这个synchronized就把run()方法锁定了,每次只能进去一个线程,去修改它的值。其他线程在抢着这把锁的key,等到前面一个线程执行完run()方法内的程序后,下一个随机线程获取了key再去执行run()方法。

 

3、  currentThread()方法是获取当前线程

Java多线程笔记 多学多练(一)

可以看出t.run()和t.start()当前线程不一致。这是因为t.start()方法是被Thread类的线程Thread-1调用的,而run方法是main方法里直接调用的,所以是main线程。

 

4、isAlive()

线程是否存活。

Java多线程笔记 多学多练(一)

 

5、sleep()方法

让真正执行的线程休眠(暂停执行)。

@Override
	 public void run() {
		try {
			System.out.println("begin...");
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("run:"+this.isAlive());
	}

打印begin...两秒后,打印后面的run:true。

 

6、getId()方法

获取线程ID。

Java多线程笔记 多学多练(一)

 

7、停止线程

停止线程很重要,一般来说有stop()强制停止线程。但因为太暴力,会让一个正在运行的线程突然终止,数据得不到同步处理,对象突然被解锁,后果很严重。

我们可以采用interrupt方法来终止线程。interrupt方法只是给这个线程标识为“要终止”的状态,而并不是调用就立即生效。

我们可以采用在run方法中判断是否是interrupt状态来抛出异常终止线程,或者return返回来终止线程。

public class ThreadDemo3 extends Thread {
	@Override
	/*public void run() {
		super.run();
		try {
			for (int i = 0; i < 10000; i++) {
				//如果线程状态为终止
				if (this.isInterrupted()) {
					System.out.println("我要停止了...");
					//抛出异常
					throw new InterruptedException();
				}
				System.out.println("i:" + i);
			}
			System.out.println("for循环外代码块..");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}*/
	public void run() {
		while (true) {
			for (int i = 0; i < 10000; i++) {
				if (this.isInterrupted()) {
					System.out.println("我要停止了...");
					// 返回结束线程
					return;
				}
				System.out.println("i:" + i);
			}
			System.out.println("for循环外代码块..");
		}
	}

	public static void main(String[] args0) {
		try {
			ThreadDemo3 threadDemo = new ThreadDemo3();
			threadDemo.start();
			Thread.sleep(100);
			threadDemo.interrupt();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}
}

两种方法终止线程 ,终止后for循环外的代码是不会执行的,直接结束了。

 Java多线程笔记 多学多练(一)

Java多线程笔记 多学多练(一)

 

8、暂停线程

thread. suspend();暂停线程

thread.resume();恢复线程

缺点是容易造成公共的同步对象独占,使其他线程访问不到公共同步对象。也就是缺点:不同步。

 

9、yieId方法

放弃当前CPU的资源,让给其他任务占用CPU。但放弃的时间不确定,可能刚刚放弃,又被占用了。

Thread.yieId();

 

10、线程优先级

 线程的优先级越高,得到的CPU资源越多。一共分为1-10等级。如果超越这个范围就会报IllegalArgumentException()异常。

线程的优先级具有继承性,也就是说子线程继承父线程优先级。默认是5。

Thread.currentThread().getPriority();//获取线程优先级

Thread.currentThread().setPriority(10);//设置线程优先级

优先级高的线程并不一定先执行完,具有随机性。

 

11、守护线程

守护线程是陪伴另一个线程,当进程中不存在非守护线程时,守护线程会自动销毁。GC(垃圾回收器)就是一个守护线程。