Java锁
java几种锁_java中有几种锁_孤雁寒窗的博客-CSDN博客
Java锁的种类_融极的博客-CSDN博客_java 锁有几种
1.多线程概念理解
计算机中的程序(Application):
(程序==软件 ( 程序:可能包含一系列进程).exe)
进程:
计算机中解决没有顺序关系的多个任务的执行机制。
进程的优点:
独立性高(安全:每个进程都会开辟自己独有的内存);
进程的缺点:
1.创建进程耗时,2. 数据共享困难
Java应用程序(Application):
程序==jvm进程
线程:
线程是进程中创建出来的。
进程中创建出来用来解决多任务的线程 共享内存 创建线程基本不耗费资源 不安全 同步锁
- 进程是重量级多任务解决技术;
- 线程是轻量级多任务解决技术。
2.线程的使用
定义:new Thread(?)
,new Thread子类(?)
启动:线程引用.start()
运行:任务线程中的run()
加入Thread.join()
中断interrupt()
: set interrupt status 设置中断状态,不是结束掉线程
在Java中创建线程的两种方式
继承java.lang.Thread类
实现java.lang.Runnable接口
1.代码案例:extends Thread
public class Test {
public static void main(String[] args) {
// 创建一个线程对象
MyThread t1 = new MyThread();
t1.start();
int n = 0;
for (int i = 0; i < 100; i++) {
n++;
}
System.out.println("我是谁,我在哪里?");
}
}
// 应该有任务
// 定义了Thread 的子类
class MyThread extends Thread{
@Override
public void run() {
System.out.println("我是第一个线程"); // 线程1:thread-1
super.run();
}
}
2.代码案例:implements Runnable
public class Test2 {
public static void main(String[] args) {
new Thread(new MyRunner()).start(); // t1
new Thread(() -> System.out.println("第三个线程")).start(); // t2
System.out.println("main............."); // main
}
}
// 定义了Runable接口的实现类
class MyRunner implements Runnable{
@Override
public void run() {
System.out.println("第二个线程");
}
}
之后这些方法就不建议使用了:
暂停
~~~~suspend()
恢复resume()
停止stop()
线程的工具方法 静态方法Thread.sleep(long)
停止多长时间Thread.yield()
让出cpuThread.currentThread()
:
3.线程协作 同步
join()
使用 synchronied
配合 Object
下的 wait
和 notify
方法实现 线程同步synchronied
相同锁名的代码块在任何时候都只能有一个线程执行wait
等待notify
唤醒notifyAll
唤醒全部
1.代码案例:休眠,阻塞
public class Test {
public static void main(String[] args) {
//new T1("t1").run();
//new Thread(new T2("t2"),"t22").start();
Thread t2 = new Thread(new T2("t2"), "t22");
T1 t1 = new T1("t1", t2);
t1.start();
t2.start();
System.out.println("main...............");
}
}
class T1 extends Thread{
private Thread t2;
public T1(String name,Thread t2) {
super(name);
this.t2 = t2;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+":"+i);
if (i == 5){
try {
t2.join(); // 阻塞他
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
// 休眠1秒钟
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class T2 implements Runnable{
private String name;
public T2(String name) {
this.name = name;
}
// 因为Runnable是,里面没有name属性,所以在上面定义一个
@Override
public void run() {
for (int i = 10; i > 0 ; i--) {
System.out.println(name+":"+i);
}
}
}
4.守护线程
setDaemon(true)
: 设置守护线程
5.线程优先级
t.setPriority(10)
: // 设置线程优先级 1~10 优先级越高,越有机会被CPU执行
代码案例:
public class Test {
public static void main(String[] args) {
// 错误代码
//Thread tt = new Thread(new T());
Thread t = new T();
// setDaemon : 设置守护线程
t.setDaemon(true);
// 设置线程优先级 1~10 优先级越高,越可能被CPU执行
t.setPriority(10);
System.out.println("开始前:"+t.isAlive());
// 中断
// 当前线程:main
t.interrupt(); //this != currentThread()
t.start();
System.out.println("开始后:"+t.isAlive());
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("main..............end");
System.out.println(t.isAlive()+"alive");
}
}
class T extends Thread{
@Override
public void run() {
{
for (int i = 0; i < 10; i++) {
System.out.println(i);
System.out.println("alive"+this.isAlive());
if (this.isInterrupted()){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//break;
}
// 中断线程:当前线程
System.out.println(Thread.currentThread().isInterrupted()); // false
if (i == 5){
System.out.println("---------------");
System.out.println(Thread.currentThread());
System.out.println(this);
// this 和 Thread.currentThread() 不相等
System.out.println((this == Thread.currentThread())+"===="); // 返回:false
//this.interrupt();
Thread.currentThread();
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
6.经典案例
6.1. 蒸馒头案例:使用了多线程,其中包含集合存取,锁,及子锁
// 蒸馒头案例:使用了多线程,其中包含集合存取,锁,及子锁
// 造成子锁的原因:是锁的嵌套
public class Test {
// 采用集合存取数据,因为数据是可变的
static List<String> data = new LinkedList<>(); // 馒头筐子
public static void main(String[] args) {
new Zuo("易建联").start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Chi("科比").start();
new Chi("詹姆斯").start();
new Chi("奥尼尔").start();
}
}
class Zuo extends Thread{
private String name;
public Zuo(String name) {
this.name = name;
}
@Override
public void run() {
while (true) {
// 唤醒锁"a"
synchronized ("a") {
for (int i = 1; i < 11; i++) {
System.out.println("生产第" + i + "个馒头");
Test.data.add("馒头" + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
"a".notifyAll();
}
try {
synchronized ("b"){
"b".wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Chi extends Thread{
private String name;
public Chi(String name) {
this.name = name;
}
@Override
public void run() {
String s = null;
while (true){
// 把锁放在synchronized ()中
synchronized ("a"){
if (Test.data.size() == 0){
try {
System.out.println(name+"发现没有馒头~");
// 唤醒锁
synchronized ("b"){
"b".notify();
}
// 加一把锁
"a".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
s = Test.data.remove(0);
System.out.println(name+"吃掉了"+s);
}
/*try {
System.out.println(name+"正在消化");
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
}
}
7.线程的另一种使用方式
Executor
执行器ExecutorService
执行器服务者
Callable
类似 Runnable
Runnable
缺点1:没有返回值,解决办法是 ,使用共享变量 加 synchronized
Runnable
缺点2:不能抛出任何异常
Callable
定义了泛型返回值,定义了声明异常
Future<Integer>
创建几个对象及存放位置
public class Test {
public static void main(String[] args) {
// 字符串对象是可以不用new就可以创建对象的,所以字符串对象是Java中的特殊对象。存放在串池中:不会被垃圾回收,不会重复
// 以下代码在jvm 内存中创建了几个对象
String ss = "aaa"; // 创建了1个对象 aaa
String ss2 = "aaa"; // 创建了0个对象
String sss = new String(ss); // 创建了1个对象 new String()
String s = new String("abc"); // 创建了2个对象 1.abc 2.new String("abc")
String s2 = new String("aaa"); // 创建了1个对象
System.out.println(ss == ss2); // true
System.out.println(ss == sss); // false
System.out.println(ss == s2); // false
// 变量或常量 + 变量或常量 等于new堆 、 常量+常量=常量 在池中
String s3 = ss + "d"; // 创建了2个对象 "d" abcd
String s4 = "aaa" + "d"; // 创建了1个对象 abcd
System.out.println(s3 == s4); // false
System.out.println(s3.equals(s4)); // true
System.out.println(s3 +"----" + s4);
// 字符串和数组是一个设计理念 字符串就是 ?数组
// 数组的特点:数组不会改变
String a = "a";
a += "b";
a += "c";
// 变量+常量
// 创建了5个对象
System.out.println("-------------");
StringBuffer sb = new StringBuffer("a"); // 创建了2个对象
sb.append("b"); // 1
sb.append("c"); // 1
System.out.println(sb.toString());
System.out.println(sb.length());
System.out.println(sb);
}
}
StringBuffer
StringBuffer//线程安全 但效率低
StringBuilder//线程不安全 但效率高
public class Test {
public static void main(String[] args) {
String line = "i am stdnet";
StringBuffer temp = new StringBuffer();
boolean flag = false;
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (c == ' ' && flag){
continue;
}
if (c != ' '){
temp.append(c);
if (flag){
flag = false;
}
}
if (c != ' ' && !flag){
temp.append(' ');
flag = true;
}
}
System.out.println(temp);
// \\s+ :正则表达式
System.out.println(line.replaceAll("\\s+"," "));
}
}
同步与异步
复制package com.bigdata09.day20.demo1;
import java.util.concurrent.*;
public class Test {
static int rs = 0;
public static void main(String[] args) throws ExecutionException, InterruptedException {
// new Thread(new T1()).start();
// System.in.read();
// int sum = rs;
// System.out.println(sum);
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> call = executorService.submit(new T2()); // 没有等待 异步(各做各的)
System.out.println("线程任务已提交,等待输出结果");
for (int i = 0;!call.isDone();i++){
if (i > 2) {
break;
}
System.out.println("等待"+(i+1));
Thread.sleep(200);
}
if (call.isDone()) {
System.out.println("这是未来结果");
}
/*System.out.println(call.get()+"这是未来结果"); // 同步结果*/
System.out.println("main...........");
}
}
class T1 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Test.rs+=1;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class T2 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 10; i++) {
sum+=i;
System.out.println(i);
int rd = (int) (Math.random()*10); // 0~9的随机数
System.out.println("sleep:"+(rd*10));
Thread.sleep(40);
}
return sum;
}
}