栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java多线程和锁

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java多线程和锁

多线程 1.线程的创建

创建线程有两种方法:
1.继承Thread类,重写run方法实现。
2.创建Thread实例并且传入Runable实例,以任务的方式创建线程。
线程通过调用start方法调用run方法

// 通过继承Thread类实现,重写run方法实现多线程
public class Test {
	public static void main(String args[]) {
		MyThread t = new MyThread();
		t.start();
	}
}

class MyThread extends Thread {
	@Override
	public void run() {
		System.out.println("线程被执行");
	}
}
//  以任务的方式创建线程
public class Test {
	public static void main(String args[]) {
		MyRunable task = new MyRunable();
		Thread t = new Thread(task);
		t.start();
	}
}

class MyRunable implements Runable {
	@Override
	public void run() {
		System.out.println("线程被执行");
	}
}
2.线程的中断 interrupt

中断一个线程只需要在调用线程的interrupt方法,然后trycache线程的InterruptedException,线程种植的时候会抛出这个异常

public class Test {
	public static void main(String[] args) {
		Thread t = new Thread() {
			@Override
			public void run() {
				try {
					System.out.println("线程被执行");
				} catch (InterruptedException e) {
					System.out.println("线程中断");
				}
			}
		};
		t.start();
		t.interrupt();
	}
}
3.线程的六种状态

New:线程被创建,还未执行
Runable:运行中的线程,正在执行run方法中的代码
Blocked:运行中的线程因为某些操作被阻塞而刮挂起
Waiting:运行中的线程,因为某些操作处于等待的状态
Time Waiting:运行中的线程,因为执行sleep方法正在计时等待
Terminated:线程被终止

4.守护线程setDaemon

守护线程是指为其他线程服务的线程。在JVM中,所有非守护线程都执行完毕后,无论有没有守护线程,虚拟机都会自动退出。 因此,JVM退出时,不必关心守护线程是否已结束 创建守护线程只需要调用线程的setDaemon方法。

Thread t=new Thread();
t.setDeamon(true);
t.start();

// 在守护线程中,编写代码要注意:守护线程不能持有任何需要关闭的资源,例如打开文件等,因为虚拟机退出时,守护线程没有任何机会来关闭文件,这会导致数据丢失。
锁 1.同步代码块的锁机制synchronized,多个线程看同一把锁-隐式锁
public class Test {
	public static void main(String[] args) {
		Runnable run = new Ticket();
		new Thread(run).start();
	}
}

class Ticket implements Runnable {
	private int count = 10;
	private Object lock = new Object();

	@Override
	public void run() {
		while (true) {
			// 三个线程看同一把锁
			synchronized (lock) {
				if (this.count > 0) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					count--;
					System.out.println(Thread.currentThread().getName());
				} else {
					break;
				}
				System.out.println("余票" + count);
			}
		}
	}
}
2.同步方法锁,synchronized修饰方法-隐式锁
public class Test {
	public static void main(String[] args) {
		Runnable run = new Ticket();
		new Thread(run).start();
	}
}

class Ticket implements Runnable {
	private int count = 10;

	@Override
	public void run() {
		while (true) {
			Boolean sell = this.sell();
			if (!sell) {
				break;
			}

		}
	}

	// synchronized 修饰任务方法
	synchronized public Boolean sell() {
		boolean sell = true;
		if (this.count > 0) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			count--;
			System.out.println(Thread.currentThread().getName());
			sell = true;
		} else {
			sell = false;
		}
		System.out.println("余票" + count);
		return sell;
	}
}
3.显示锁-ReentrantLock,实例化一个ReentrantLock,在需要加锁的地方调用lock方法,在需要解锁的地方调用unLock方法.
public class Test {
	public static void main(String[] args) {
		Runnable run = new Ticket();
		new Thread(run).start();
	}
}

class Ticket implements Runnable {
	private int count = 10;
	// 实例化锁
	private Lock l = new ReentrantLock();

	@Override
	public void run() {
		while (true) {
			// 加锁
			l.lock();
			if (this.count > 0) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				count--;
				System.out.println(Thread.currentThread().getName());
			} else {
				break;
			}
			System.out.println("余票" + count);
			// 解锁
			l.unlock();
		}
	}
}
4.公平锁和不公平锁

公平锁:排队取锁 不公平锁:不排队,抢锁,java默认为非公平锁 设置一个锁为公平锁,只需要实例化ReentrantLock的时候传入true

public class Test {
	public static void main(String[] args) {
		// 传入true表示此锁为公平锁
		Lock lock = new ReentrantLock(true);
	}
}
5.死锁

死锁产生的条件是多线程各自持有不同的锁,并互相试图获取对方已持有的锁,导致无限等待; 避免死锁的方法是多线程获取锁的顺序要一致。

6.wait和notify用于多线程协调运行

在synchronized内部可以调用wait()使线程进入等待状态;
必须在已获得的锁对象上调用wait()方法;
在synchronized内部可以调用notify()或notifyAll()唤醒其他等待线程;
必须在已获得的锁对象上调用notify()或notifyAll()方法;
已唤醒的线程还需要重新获得锁后才能继续执行。

7.Callable带返回值的线程
public class Test {
	public static void main(String[] args) throws ExecutionException, InterruptedException {
		Call c = new Call();
		// 使用Future获取线程的返回值,线程池中提交任务后也会返回一个Future类型
		FutureTask f = new FutureTask<>(c);
		Thread t = new Thread(f);
		t.start();
		int val = 0;
		val = f.get();
		System.out.println("返回值为" + val);
		System.out.println("同步打印");
	}
}

class Call implements Callable {
	@Override
	public Integer call() throws Exception {
		Thread.sleep(3000);
		return 100;
	}
}

8.线程池

线程池:存放线程的容器
线程执行过程:创建线程,创建任务,执行任务,关闭线程
耗时的步骤:创建线程,关闭线程
线程池分类:缓存线程池,定长线程池,单线程线程池,周期性任务定长线程池

public class Test {
	public static void main(String[] args) throws InterruptedException {
		// 1.缓存线程池
		ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
		// 2.定长线程池
		ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
		// 3.单线程线程池
		ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

		ExecutorService service = singleThreadPool;
		// 线程池中添加并执行任务
		for (int i = 0; i < 5; i++) {
			service.execute(new Runnable() {
				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName());
				}
			});
		}
		// 祝线程sleep
		Thread.sleep(1000);
		// 下面的任务使用缓存的线程执行
		service.execute(new Runnable() {
			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName());
			}
		});

		// 4.周期性任务定长线程池
		ScheduledExecutorService scheduleService = Executors.newScheduledThreadPool(2);
		
		scheduleService.schedule(new Runnable() {
			@Override
			public void run() {
				System.out.println("床前明月光");
			}
		}, 5, TimeUnit.SECONDS);

		
		scheduleService.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				System.out.println("5s种后执行,每隔1s执行一次");
			}
		}, 5, 1, TimeUnit.SECONDS);
	}
}
9.lambda表达式

Lambda 表达式是一个匿名函数(对于 Java 而言并不很准确,但这里我们不纠结这个问题)。简单来说,这是一种没有声明的方法,即没有访问修饰符,返回值声明和名称。
在仅使用一次方法的地方特别有用,方法定义很短。它为我们节省了,如包含类声明和编写单独方法的工作。 Java 中的 Lambda 表达式通常使用语法是 (argument) -> (body),比如:

(arg1, arg2...) -> { body }
(type1 arg1, type2 arg2...) -> { body }
public class Learn0304_8 {
	public static void main(String[] args) {
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("床前明月光");
			}
		});
		t.start();

		// lambda
		Thread t2 = new Thread(() -> System.out.println("床前明月光"));
		t2.start();

		// custom
		print(new getNumber() {
			@Override
			public int sum(int x, int y) {
				return x + y;
			}
		}, 100, 200);

		// lambda
		print((int x, int y) -> {
			return x + y;
		}, 100, 200);
	}

	static public void print(getNumber g, int x, int y) {
		System.out.println(g.sum(x, y));
	}
}

interface getNumber {
	int sum(int x, int y);
}

10.网络编程 1.tcp编程

在开发网络应用程序的时候,我们又会遇到Socket这个概念。Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络

使用Socket进行网络编程时,本质上就是两个进程之间的网络通信。其中一个进程必须充当服务器端,它会主动监听某个指定的端口,另一个进程必须充当客户端,它必须主动连接服务器的IP地址和指定端口,如果连接成功,服务器端和客户端就成功地建立了一个TCP连接,双方后续就可以随时发送和接收数据。
因此,当Socket连接成功地在服务器端和客户端之间建立后:
对服务器端来说,它的Socket是指定的IP地址和指定的端口号;
对客户端来说,它的Socket是它所在计算机的IP地址和一个由操作系统分配的随机端口号

// server
public class TestServer {
	public static void main(String[] args) throws IOException {
		ServerSocket server = new ServerSocket(4000);
		// 等待客户端连接
		

		
		while (true) {
			Socket socket = server.accept();
			new Thread() {
				@Override
				public void run() {
					try {
						// 获取输入流
						

						// 输出流
						OutputStream os = socket.getOutputStream();
						PrintStream ps = new PrintStream(os);
						ps.println("message from server");
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}.start();
		}
	}
}

// client
public class TestClient {
	public static void main(String[] args) throws IOException {
		Socket socket = new Socket("127.0.0.1", 4000);
		InputStream is = socket.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is));
		String msg = br.readLine();
		System.out.println("客户端接收到消息:" + msg);
		OutputStream os = socket.getOutputStream();
		PrintStream ps = new PrintStream(os);
		ps.println("message from client");
	}
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/284812.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号