线程
在调用start()方法之后,start()与后面的代码并行运行,不分前后顺序
定义
public class TestThread extends Thread{
public void run(){
System.out.println("多线程运行的代码");
for (int i = 0; i < 5; i++) {
System.out.println("多线程的运行逻辑:"+i);
}
}
}
实现
Thread t=new TestThread();
t.start();
定义
ublic class TestRunnable implements Runnable{
@Override
public void run() {
System.out.println("多线程运行的代码");
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"多线程的运行逻辑:"+i);
}
}
}
实现
Thread t1= new Thread(new TestRunnable(),"Test");
t1.start();
Thread t2=new Thread(new TestRunnable());
t2.start();
一般使用实现接口的方式来实现多线程,达到共享目的
定义
ublic class TestRunnable implements Runnable{
int count=0;
@Override
public void run() {
System.out.println("多线程运行的代码");
for (int i = 0; i < 5; i++) {
count++;
System.out.println(Thread.currentThread().getName()+"多线程的运行逻辑:"+count);
}
}
}
实现
public class Test {
public static void main(String[] args) {
Runnable ran=new TestRunnable();
Thread t1= new Thread(ran,"Test");
t1.start();
Thread t2=new Thread(ran ,"Test");
t2.start();
System.out.println("===================1");
System.out.println("===================2");
System.out.println("===================3");
}
}
结果count=10
优先级越高,被执行的概率越大
Synchronized的使用方法
注意:
1)当两个线程同时对一个对象的一个方法进行操作,只有一个线程能够抢到锁。因为一个对象只有一把锁,一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,就不能访问该对象的其他synchronized实例方法,需要等到对象被释放后才能获取,但是在对象没有被释放前,其他线程可以访问非synchronized修饰的方法
2)两个线程实例化两个不同的对象,但是访问的方法是静态的,两个线程发生了互斥(即一个线程访问,另一个线程只能等着),因为静态方法是依附于类而不是对象的,当synchronized修饰静态方法时,锁是class对象。
静态方法加同步锁,对于所有的对象都是同一个锁
用this锁当前代码块是代表当前的对象,如果在其他方法中也有synchronized(this)的代码使用的都是同一个同步锁
Synchronize修饰实例方法:
public class Test02 {
public static void main(String[] args) {
Account account=new Account();
User u_wexin=new User(account,2000);
User u_zhifubao=new User(account,2000);
Thread wexin=new Thread(u_wexin,"微信");
Thread zhifubao=new Thread(u_zhifubao,"支付宝");
wexin.start();zhifubao.start();
}
}
class Account{
public static int money=3000 ;
public synchronized void drawing(int m){
String name=Thread.currentThread().getName();
if(m>money){
System.out.println(name+"操作,账户金额不足:"+money);
}else {
System.out.println(name+"操作,账户原有金额: "+money);
System.out.println(name+"操作,取款金额: "+m);
System.out.println(name+"操作,取款操作:账户原有金额: "+money+"-"+"取款金额"+m);
money=money-m;
System.out.println(name+"操作,账户剩余金额: "+money);
}
}
}
class User implements Runnable{
Account account;
int money;
public User(Account account, int money) {
this.account=account;
this.money=money;
}
@Override
public void run() {
account.drawing(money);
}
}
当一个线程正在访问一个对象的 synchronized 实例方法,那么其他线程不能访问该对象的其他 synchronized 方法,毕竟一个对象只有一把锁,当一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,所以无法访问该对象的其他synchronized实例方法,但是其他线程还是可以访问该实例对象的其他非synchronized方法
Synchronized作用于静态方法
public class Test02 {
public static void main(String[] args) {
Account account=new Account();
Account account1=new Account();
User u_wexin=new User(account,2000);
User u_zhifubao=new User(account1,2000);
Thread wexin=new Thread(u_wexin,"微信");
Thread zhifubao=new Thread(u_zhifubao,"支付宝");
wexin.start();zhifubao.start();
}
}
class Account{
public static int money=3000 ;
public static synchronized void drawing(int m){
String name=Thread.currentThread().getName();
if(m>money){
System.out.println(name+"操作,账户金额不足:"+money);
}else {
System.out.println(name+"操作,账户原有金额: "+money);
System.out.println(name+"操作,取款金额: "+m);
System.out.println(name+"操作,取款操作:账户原有金额: "+money+"-"+"取款金额"+m);
money=money-m;
System.out.println(name+"操作,账户剩余金额: "+money);
}
}
}
class User implements Runnable{
Account account;
int money;
public User(Account account, int money) {
this.account=account;
this.money=money;
}
@Override
public void run() {
account.drawing(money);
}
}
当synchronized作用于静态方法时,其锁就是当前类的class对象锁。由于静态成员不专属于任何一个实例对象,是类成员,因此通过class对象锁可以控制静态 成员的并发操作。
Sychronized同步代码块
public void drawing1(int m){
synchronized (this){
String name=Thread.currentThread().getName();
if(m>money){
System.out.println(name+"操作,账户金额不足:"+money);
}else {
System.out.println(name+"操作,账户原有金额: "+money);
System.out.println(name+"操作,取款金额: "+m);
System.out.println(name+"操作,取款操作:账户原有金额: "+money+"-"+"取款金额"+m);
money=money-m;
System.out.println(name+"操作,账户剩余金额: "+money);
}
}
}
定义不同的对象用不同的锁即不产生互斥,各走各的
public void drawing2(int m,Account a){
synchronized (a){
String name=Thread.currentThread().getName();
if(m>money){
System.out.println(name+"操作,账户金额不足:"+money);
}else {
System.out.println(name+"操作,账户原有金额: "+money);
System.out.println(name+"操作,取款金额: "+m);
System.out.println(name+"操作,取款操作:账户原有金额: "+money+"-"+"取款金额"+m);
money=money-m;
System.out.println(name+"操作,账户剩余金额: "+money);
}
}
}
调用这些方法的前提是都要有同步锁
public void drawing2(int m,Account a){
synchronized (a){
String name=Thread.currentThread().getName();
if(name.equals("微信")){
try {
a.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(m>money){
System.out.println(name+"操作,账户金额不足:"+money);
}else {
System.out.println(name+"操作,账户原有金额: "+money);
System.out.println(name+"操作,取款金额: "+m);
System.out.println(name+"操作,取款操作:账户原有金额: "+money+"-"+"取款金额"+m);
money=money-m;
System.out.println(name+"操作,账户剩余金额: "+money);
}
if(name.equals("支付宝")){
try {
// a.notify();
a.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
实现:
public static void main(String[] args) {
Account account=new Account();
User u_wexin=new User(account,2000);
User u_zhifubao=new User(account,2000);
Thread wexin=new Thread(u_wexin,"微信");
Thread zhifubao=new Thread(u_zhifubao,"支付宝");
wexin.start();zhifubao.start();
}
public class Test03 {
public static void main(String[] args) {
Clerk c=new Clerk();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (c){
while(true){
if(c.ProductNum==0){
System.out.println("产品数为4,开始生产");
while(c.ProductNum<4){
c.ProductNum++;
System.out.println("库存:"+c.ProductNum);
}
System.out.println("产品数为:"+c.ProductNum+" ,停止生产");
c.notify();
}else {
try {
c.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}, "生产者").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (c){
while(true){
if(c.ProductNum==4){
System.out.println("产品数为4,开始消费");
while(c.ProductNum>0){
c.ProductNum--;
System.out.println("库存:"+c.ProductNum);
}
System.out.println("产品数为:"+c.ProductNum+" ,停止消费");
c.notify();
}else {
try {
c.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}, "消费者").start();
}
}
class Clerk{
public static int ProductNum=0;
}