Java多线程编程(基础,synchronized)

第一章:Java多线程技能

Java实现多线程的方式

1 继承Thread类(不支持多继承),2 实现Runnable接口

线程调用有随机性。

 

package com.java.mul;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		
		MyThread mythread = new MyThread();
		mythread.setName("myThread");
		
		mythread.start();
		for(int count = 0;count<10;count++) {
			int time = (int) (Math.random() * 1000);
			Thread.sleep(time);
			System.out.println("main="+Thread.currentThread().getName());
		}
		
		System.out.println("finish");
	}

}


package com.java.mul;

public class MyThread extends Thread{
	@Override
	public void run() {
		super.run();
		System.out.println("MyThread");
		for(int count = 0;count<10;count++) {
			
			try {
				int time = (int) (Math.random() * 1000);
				Thread.sleep(time);
				System.out.println("run="+Thread.currentThread().getName());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
}

结果

MyThread
main=main
run=myThread
main=main
run=myThread
main=main
main=main
run=myThread
run=myThread
main=main
run=myThread
main=main
run=myThread
run=myThread
main=main
run=myThread
main=main
run=myThread
main=main
main=main
finish
run=myThread

共享与不共享

共享(产生了非线程安全问题)

package com.java.mul;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		MyThread mythread = new MyThread();
		Thread a = new Thread(mythread,"A");
		Thread b = new Thread(mythread,"B");
		Thread c = new Thread(mythread,"C");
		Thread d = new Thread(mythread,"D");
		Thread e = new Thread(mythread,"E");
		a.start();
		b.start();
		c.start();
		d.start();
		e.start();
	}

}

package com.java.mul;

public class MyThread extends Thread{
	private int count = 5;

	
	@Override
	public void run() {
		super.run();
		count--;
			
		System.out.println("由"+Thread.currentThread().getName()+"计算,count="+count);
		

	}
}

package com.java.mul;

public class myRunnable implements Runnable{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("run");
	}
	
}

解决:synchronized

package com.java.mul;

public class MyThread extends Thread{
	private int count = 5;

	
	@Override
	synchronized public void run() {
		super.run();
		count--;
			
		System.out.println("由"+Thread.currentThread().getName()+"计算,count="+count);
		

	}
}

(isAlive,在this和Thread.currentThread()之间,会有不同的调用结果,主要原因在于this和Thread.currentThread()的差异)

停止线程:

Thread.stop()(不安全)(一般不用)

大多数使用Thread.interrupt()(interrupt方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程)

 

Thread.interrupted()

		Thread.currentThread().interrupt();
		System.out.println("是否停止1? = " + Thread.interrupted());
		System.out.println("是否停止2? =" + Thread.interrupted());
		System.out.println("end!");

结果为

是否停止1? = true
是否停止2? =false
end!

这样的结果是因为,interrupted的第一次调用,会返回true并且清除当前中断当前interrupted检测到为true的状态

与interrupted共同使用的不用break,用throw,这样可以继续执行后面的代码

package com.java.mul;

public class MyThread extends Thread{
	private int count = 5;

	
	@Override
	public void run() {
		super.run();
		for(int i = 0;i<500000;i++) {
			if(this.interrupted()) {
				System.out.println("已经停止");
				//break;
				try {
					throw new InterruptedException();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			System.out.println("i="+i+1);
		}
		System.out.println("在for下面");
	}
}



package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		MyThread thread = new MyThread();
		thread.start();
		Thread.sleep(2000);
		thread.interrupt();
	}

}

如果在sleep状态下停止线程,会进入catch语句,并且清除停止状态值,使之变成false

先停止,再sleep,也不行,会进入catch

package com.java.mul;

public class MyThread extends Thread{
	private int count = 5;

	
	@Override
	public void run() {
		super.run();
		try {
			for(int i=0;i<100000;i++) {
				System.out.println("i=" +(i+1));
			}
			System.out.println("run begin");
			Thread.sleep(200000);
			System.out.println("run end");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			System.out.println("sleep stop");
			e.printStackTrace();
		}
		
	}
}

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		MyThread thread = new MyThread();
		thread.start();
		thread.interrupt();
		System.out.println("end!");
		
	}

}

 

 

stop方法强制停止线程(会抛出不显示捕捉的ThreadDeath异常)(stop方法已经被作废)

interrupted与return结合也能实现停止线程的效果,不过还是推荐使用throw

 

暂停线程

suspend()方法暂停线程(过期作废的方法)

resume()方法恢复暂停线程(过期作废的方法)

在使用这两个方法的时候,如果使用不当,极易造成公共的同步对象的独占。

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		MyThread thread = new MyThread();
		thread.start();
		Thread.sleep(5000);
		thread.suspend();
		System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI());
		Thread.sleep(5000);
		System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI());
		
		thread.resume();
		Thread.sleep(5000);
		
		thread.suspend();
		System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI());
		
		Thread.sleep(5000);
		System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI());
	}

}

package com.java.mul;

public class MyThread extends Thread{
	private int count = 5;
	private long i = 0;
	public long getI() {
		return i;
	}
	
	public void setI(long i) {
		this.i = i;
	}
	

	
	@Override
	public void run() {
		while(true) {
			i++;
		}
	}
}

 

yield

(作用是放弃当前CPU资源,将它让给其他任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片)

package com.java.mul;

public class MyThread extends Thread{

	@Override
	public void run() {
		long beginTime = System.currentTimeMillis();
		int count=0;
		for(int i=0;i<50000000;i++) {
			Thread.yield();
			count = count + (i + 1);
		}
		long endTime = System.currentTimeMillis();
		System.out.println("用时:"+(endTime - beginTime)+"毫秒! ");
	}
}

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		MyThread thread = new MyThread();
		thread.start();
	}

}

setPriority设置线程优先级(1-10),优先级具有继承性,比如A线程启动B线程,那么他们的优先级一致。

优先级具有规则性,高优先级的线程总是大部分先执行完,但是高优先级的并不是每次都是先执行完。

 

守护线程

当进程中不存在非守护线程了,守护线程自动销毁,典型的守护线程(垃圾回收线程(GC))

package com.java.mul;

public class MyThread extends Thread{
	private int i= 0;
	@Override
	public void run() {
		long beginTime = System.currentTimeMillis();
		try {
			while(true) {
				i++;
				System.out.println("i=" + (i));
				Thread.sleep(1000);
			}
		}catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
}

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		MyThread thread = new MyThread();
		thread.setDaemon(true);
		thread.start();
		Thread.sleep(5000);
		System.out.println("stop");
	}

}

第二章:对象及变量的并发访问

线程安全

1 private修饰的变量

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		
		HasSelfPrivateNum numRef = new HasSelfPrivateNum();
		MyThread thread = new MyThread(numRef);
		thread.start();
		ThreadA threada = new ThreadA(numRef);
		threada.start();

	}

}

package com.java.mul;

public class HasSelfPrivateNum {
	public void addI(String username) {
		try {
			int num = 0;
			if(username.equals("a")) {
				num = 100;
				System.out.println("a set over");
				Thread.sleep(2000);
			}else {
				num = 200;
				System.out.println("b set over");
			}
			System.out.println(username + " num=" + num);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

package com.java.mul;

public class MyThread extends Thread{
	private HasSelfPrivateNum numRef;
	public MyThread(HasSelfPrivateNum numRef) {
		super();
		this.numRef = numRef;
	}

	@Override
	public void run() {
		super.run();
		numRef.addI("a");
		
	}
}

package com.java.mul;

public class ThreadA extends Thread{
	private HasSelfPrivateNum numRef;
	public ThreadA(HasSelfPrivateNum numRef) {
		super();
		this.numRef = numRef;
	}

	@Override
	public void run() {
		super.run();
		numRef.addI("b");
		
	}
}

 

synchronized锁重入

在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远可以得到锁的,如果不可锁重入的话,就会造成死锁。

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		MyThread thread = new MyThread();
		thread.start();
	}
}

package com.java.mul;

public class MyThread extends Thread{

	@Override
	public void run() {
		Service service = new Service();
		service.service1();
		
	}
}

package com.java.mul;

public class Service {
	synchronized public void service1() {
		System.out.println("service1");
		service2();
	}
	synchronized public void service2() {
		System.out.println("service2");
		service3();
	}
	synchronized public void service3() {
		System.out.println("service3");
	}
}

可重入锁也支持在父子类继承的环境中

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		MyThread thread = new MyThread();
		thread.start();
	}
}

package com.java.mul;

public class MyThread extends Thread{

	@Override
	public void run() {
		Sub sub = new Sub();
		sub.operateISubMethod();
		
	}
}

package com.java.mul;

public class Main {
	public int i = 10;
	synchronized public void operateIMainMethod() {
		try {
			i--;
			System.out.println("main print i=" + i);
			Thread.sleep(100);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package com.java.mul;

public class Sub extends Main{
	synchronized public void operateISubMethod() {
		try {
			while(i>0) {
				i--;
				System.out.println("sub print i=" + i);
				Thread.sleep(100);
				this.operateIMainMethod();
			}
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

出现异常,锁自动释放

同步不可以被继承

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Sub subRef = new Sub();
		MyThreadA a = new MyThreadA(subRef);
		a.setName("A");
		a.start();
		MyThreadB b = new MyThreadB(subRef);
		b.setName("B");
		b.start();
	}
}

package com.java.mul;

public class Main {
	synchronized public void serviceMethod() {
		try {
			
			System.out.println("int main" + Thread.currentThread().getName() + "time="+ System.currentTimeMillis());
			
			Thread.sleep(5000);
			System.out.println("int main" + Thread.currentThread().getName() + "time="+ System.currentTimeMillis());
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package com.java.mul;

public class Sub extends Main{
	public void serviceMethod() {
		try {
			System.out.println("int main" + Thread.currentThread().getName() + "time="+ System.currentTimeMillis());
			
			Thread.sleep(5000);
			System.out.println("int main" + Thread.currentThread().getName() + "time="+ System.currentTimeMillis());
			super.serviceMethod();
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package com.java.mul;

public class MyThreadA extends Thread{
	private Sub sub;
	public MyThreadA(Sub sub) {
		super();
		this.sub = sub;
	}
	
	@Override
	public void run() {
		sub.serviceMethod();
	}
}

package com.java.mul;

public class MyThreadB extends Thread{
	private Sub sub;
	public MyThreadB(Sub sub) {
		super();
		this.sub = sub;
	}
	
	@Override
	public void run() {
		sub.serviceMethod();
	}
}

synchronized(this)同步语句块,是对某一个对象进行加锁

当线程访问同一个object的一个synchronized(this)代码块时,其他线程对同一个object中的所有其他synchronized(this)同步代码块的访问将被阻塞

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		ObjectService service = new ObjectService();
		MyThreadA a = new MyThreadA(service);
		a.setName("A");
		a.start();
		MyThreadB b = new MyThreadB(service);
		b.setName("B");
		b.start();
	}
}

package com.java.mul;

public class MyThreadA extends Thread{
	private ObjectService service;
	public MyThreadA(ObjectService service) {
		super();
		this.service = service;
	}
	
	@Override
	public void run() {
		super.run();
		service.serviceMethodA();
	}
}

package com.java.mul;

public class MyThreadB extends Thread{
	private ObjectService service;
	public MyThreadB(ObjectService service) {
		super();
		this.service = service;
	}
	
	@Override
	public void run() {
		service.serviceMethodB();
	}
}

package com.java.mul;

public class ObjectService {
	public void serviceMethodA() {
		try {
			synchronized(this) {
				System.out.println("A begin time="+ System.currentTimeMillis());
				Thread.sleep(2000);
				System.out.println("A end time="+ System.currentTimeMillis());
			}
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void serviceMethodB() {
		synchronized(this) {
			System.out.println("B begin time="+ System.currentTimeMillis());
			System.out.println("B end time="+ System.currentTimeMillis());
		}
	}
}

synchronized(其他对象)(与this是异步的)(因为this与其他对象,不是一个对象,不是一个对象监视器,异步)

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		ObjectService service = new ObjectService();
		MyThreadA a = new MyThreadA(service);
		a.setName("A");
		a.start();
		MyThreadB b = new MyThreadB(service);
		b.setName("B");
		b.start();
	}
}


package com.java.mul;

public class MyThreadA extends Thread{
	private ObjectService service;
	public MyThreadA(ObjectService service) {
		super();
		this.service = service;
	}
	
	@Override
	public void run() {
		super.run();
		service.setUsernamePassword("b", "aa");
	}
}

package com.java.mul;

public class MyThreadB extends Thread{
	private ObjectService service;
	public MyThreadB(ObjectService service) {
		super();
		this.service = service;
	}
	
	@Override
	public void run() {
		service.setUsernamePassword("b", "bb");
	}
}

package com.java.mul;

public class ObjectService {
	private String usernameParam;
	private String passwordParam;
	private String anyString = new String();
	public void setUsernamePassword(String username,String password) {
		try {
			synchronized(anyString) {
				System.out.println("name:"+Thread.currentThread().getName()+"zzai"+System.currentTimeMillis()+"enter");
				usernameParam = username;
				Thread.sleep(3000);
				passwordParam = password;
				System.out.println("name:"+Thread.currentThread().getName()+"zzai"+System.currentTimeMillis()+"leave");
				
				
			}
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void serviceMethodA() {
		try {
			synchronized(this) {
				System.out.println("A begin time="+ System.currentTimeMillis());
				Thread.sleep(2000);
				System.out.println("A end time="+ System.currentTimeMillis());
			}
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void serviceMethodB() {
		synchronized(this) {
			System.out.println("B begin time="+ System.currentTimeMillis());
			System.out.println("B end time="+ System.currentTimeMillis());
		}
	}
}

synchronized关键字可以应用在static静态方法上,如果这样写,是对当前java文件对应的Class类进行持锁。class锁可以对类的所有对象示例起作用。效果与synchronized(class)代码块的作用一致。(synchronized(Service.class))

JVM中具有String常量池缓存的功能,当synchronized(string)同步块与String联合使用时,要注意常量池带来的一些例外。

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Service service = new Service();
		MyThreadA a = new MyThreadA(service);
		a.setName("A");
		a.start();
		MyThreadB b = new MyThreadB(service);
		b.setName("B");
		b.start();
	}
}

package com.java.mul;

public class MyThreadA extends Thread{
	private Service service;
	public MyThreadA(Service service) {
		super();
		this.service = service;
	}
	
	@Override
	public void run() {
		service.print("AA");
	}
}

package com.java.mul;

public class MyThreadB extends Thread{
	private Service service;
	public MyThreadB(Service service) {
		super();
		this.service = service;
	}
	
	@Override
	public void run() {
		service.print("AA");;
	}
}

package com.java.mul;

public class Service {
	public static void print(String stringParam) {
		try {
			synchronized (stringParam) {
				while(true) {
					System.out.println(Thread.currentThread().getName());
					Thread.sleep(1000);
				}
			}
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

B线程会被阻塞,因为String的两个值都为AA,两个线程持有相同的锁。这就是String常量池带来的问题,因此大多数情况下,同步synchronized代码块都不使用String作为锁对象。而改用new Object()实例化一个Object对象,但它并不放入缓存中。

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Service service = new Service();
		MyThreadA a = new MyThreadA(service);
		a.setName("A");
		a.start();
		MyThreadB b = new MyThreadB(service);
		b.setName("B");
		b.start();
	}
}

package com.java.mul;

public class MyThreadA extends Thread{
	private Service service;
	public MyThreadA(Service service) {
		super();
		this.service = service;
	}
	
	@Override
	public void run() {
		service.print(new Object());
	}
}

package com.java.mul;

public class MyThreadB extends Thread{
	private Service service;
	public MyThreadB(Service service) {
		super();
		this.service = service;
	}
	
	@Override
	public void run() {
		service.print(new Object());
	}
}

package com.java.mul;

public class Service {
	public static void print(Object stringParam) {
		try {
			synchronized (stringParam) {
				while(true) {
					System.out.println(Thread.currentThread().getName());
					Thread.sleep(1000);
				}
			}
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

 

同步代码块synchronized(class2)对class2上锁之后,其他线程只能以同步的方式调用class2中的静态同步方法。

只要对象不变,即使对象的属性被改变,运行结果也是同步的。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值