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

java之多线程

程序员文章站 2023-12-23 12:54:22
...

layout: post title: "java之多线程" subtitle: " "多线程的基础知识"" date: 2018-10-07 06:00:00 author: "青乡" header-img: "img/post-bg-2015.jpg" catalog: true tags: - multi thread

什么是死锁?死锁是怎么发生的?

1.2个线程
2.2个锁对象

每个线程各自拥有一个锁对象,同时,每个线程还要去获取另外一个锁对象,但是这个锁对象已经被对方线程占有。


写一个死锁的代码?

锁对象1
锁对象2

方法1(){
    synchronized(锁对象1){
        synchronized(锁对象2){
            ...
        }
    }
}


方法2(){
    synchronized(锁对象2){
        synchronized(锁对象1){
            ...
        }
    }
}
复制代码

为什么会出现数据不同步的情况?

1.多线程
2.对象堆

主要是从内存的角度看,对象堆里的数据,多线程共享。


代码 //多线程访问对象堆里的数据

package gzh.test.multiThread;

/**
 * 启动程序
 * 
 * ---调试技巧---
 * 如何才能不按线程顺序输出?
 * 调试的时候,在线程1打断点,就会先执行线程2的任务。
 * @author gongzhihao
 *
 */
public class MultiThreadTest {
	static Data d = new Data(); //对象堆里的数据,线程共享

	public static void main(String[] args) {	
		//初始数据
		System.out.println("a=" + d.a + ", flag=" + d.flag);
		System.out.println();
		
		//多线程访问数据
//		for (int i = 0; i < 10; i++) {
//			Thread t1 = new Thread(new TaskThread1());
//			t1.start();
//		}
		
		Thread t1 = new Thread(new TaskThread1());
		t1.start();
		
		Thread t2 = new Thread(new TaskThread2());
		t2.start();
	}

}

复制代码
package gzh.test.multiThread;

/**
 * 任务线程
 * @author gongzhihao
 *
 */
public class TaskThread1 implements Runnable{
	public void run() {
		System.out.println("current thread: " + Thread.currentThread() + ", MultiThreadTest.d: " + MultiThreadTest.d);
		MultiThreadTest.d.writer();
	}

}

复制代码
package gzh.test.multiThread;

/**
 * 任务线程
 * @author gongzhihao
 *
 */
public class TaskThread2 implements Runnable{
	public void run() {
		System.out.println("current thread: " + Thread.currentThread() + ", MultiThreadTest.d: " + MultiThreadTest.d);
		MultiThreadTest.d.reader();
	}

}

复制代码
package gzh.test.multiThread;

/**
 * 数据
 * @author gongzhihao
 *
 */
class Data {
	int a = 0;
	boolean flag = false;

	public synchronized void writer() {
		a = 1;
		System.out.println("a=" + a);
		flag = true;
		System.out.println("flag=" + flag);
	}

	public synchronized void reader() {
		System.out.println("flag=" + flag);
		if (flag) {
			System.out.println("flag=" + flag);
			int i = a;
			System.out.println("i=" + i);
		}
	}
}

复制代码
输出结果
a=0, flag=false

current thread: Thread[Thread-0,5,main], MultiThreadTest.d: [email protected] //看共享数据id,可以看出来是同一个对象67565b6a
current thread: Thread[Thread-1,5,main], MultiThreadTest.d: [email protected]
flag=false
a=1
flag=true

复制代码

为什么要同步?

确保同一时刻,只有一个线程写数据。

进程和线程

进程

与线程的关系 包含多个线程。


如何通信?
不同进程是不同的地址空间。即不同进程里的数据互相不能访问。

那不同进程如何通信? 每个进程是一个应用程序,ip+端口 唯一的确定一个应用程序,所以不同程序/进程的通信底层都是通过ip+端口,先定位到哪一台机器的哪一个程序,然后再调用该程序提供的服务。例如,分布式服务之间的通信,是调用别的机器的远程服务。


进程怎么通信?
1.套接字
2.消息中间件
3.远程服务

2个不同的程序,可以实现数据互通!

线程

与进程的关系 属于进程。 一个进程一般是一个应用程序,一个应用程序要完成多个任务,就会出现多线程。这是多线程最大的作用。


如何通信?
共用同一个进程空间(即内存),所以会导致数据不一致。这是最大的问题。


如何解决数据不一致的问题?
基本上所有的多线程和同步技术都是在解决这个问题。

线程的状态

1.新建
new Thread();

2.在运行
Thread.start();

3.睡眠/阻塞
.sleep();

IO阻塞; //本地数据访问、网络数据访问,都会出现访问数据阻塞,例如,数据量太大,网络不好。

4.再次运行
睡醒了;

IO完毕。

5.结束/死亡
代码运行完毕。

怎么同步

有2种方法,
1.基础
即常用方法。一般使用同步关键字,同步方法或代码块。

2.提高
jdk 线程池。

jdk 高级并发类。

以上都是属于jdk并发包的内容。


怎么使用?


底层原理?

java并发包

线程池

并发集合和映射

显式锁

优点
1.显式锁
2.可以控制同步粒度

还有优点
1.中断
2.超时

并发原子

happen-before

代码是有先后执行顺序的。这个先后执行顺序就是所谓的happen-before规则。

指令重排序

就是多线程的代码没有先后顺序,完全随机。

线程组ThreadGroup

作用是方便统一管理线程,以及线程的各个特性。

每个线程都属于一个线程组,还有一个父线程组。

参考

1.官方文档 docs.oracle.com/javase/tuto…

2.1)讲并发的有一本书 很好 看那一本书就够

2)还有一本是jdk 并发包 作者写的

3.再结合google 和 *

转载于:https://juejin.im/post/5c0763046fb9a049f9125b03

上一篇:

下一篇: