public class JoinThread extends Thread
{
static int i = 0;
public JoinThread(String name)
{
super(name);
}
public void run()
{
while(i < 100)
{
i++;
System.out.println(getName() + " " + i);
}
}
public static void main(String[] args)throws Exception
{
JoinThread t = new JoinThread("后台");
t.start();
while(i<100)
{
System.out.println(Thread.currentThread().getName() + " " + i);
}
System.out.println("停");
}
}
====================================================================================
运行结果是这样的
后台 1
后台 2
main 1
main 3
后台 3
main 3
后台 4
.........
main 97
后台 98
main 98
后台 99
main 99
后台 100
停================================================================================ 问题一:为什么运行结果不是这样
后台 1
后台 2
main 3
main 4
后台 5
main 6
后台 7
.........
main 95
后台 96
main 97
后台 98
main 99
后台 100
停================================================================== 问题一: 怎么只有 一个i 会在不同的线程里面出现不同的值呢? 问题二: i的内存内部是怎么实现的?想不通怎么一个变量会在不同线程中展示出两个不同的值。
{
static int i = 0;
public JoinThread(String name)
{
super(name);
}
public void run()
{
while(i < 100)
{
i++;
System.out.println(getName() + " " + i);
}
}
public static void main(String[] args)throws Exception
{
JoinThread t = new JoinThread("后台");
t.start();
while(i<100)
{
System.out.println(Thread.currentThread().getName() + " " + i);
}
System.out.println("停");
}
}
====================================================================================
运行结果是这样的
后台 1
后台 2
main 1
main 3
后台 3
main 3
后台 4
.........
main 97
后台 98
main 98
后台 99
main 99
后台 100
停================================================================================ 问题一:为什么运行结果不是这样
后台 1
后台 2
main 3
main 4
后台 5
main 6
后台 7
.........
main 95
后台 96
main 97
后台 98
main 99
后台 100
停================================================================== 问题一: 怎么只有 一个i 会在不同的线程里面出现不同的值呢? 问题二: i的内存内部是怎么实现的?想不通怎么一个变量会在不同线程中展示出两个不同的值。
public class Test extends Thread {
static int i = 0;
static Object o = new Object(); public Test(String name) {
super(name);
} public void run() {
while (i < 1000) {
System.out.println(getName() + " " + i);
i++;
Thread.yield(); }
} public static void main(String[] args) throws Exception { Test t = new Test("后台");
t.start();
while (i < 1000) {
System.out.println(Thread.currentThread().getName() + " " + i);
i++;
Thread.yield();
}
System.out.println("停");
}
}
试试这个
public class Test extends Thread {
static int i = 0;
static Object o = new Object(); public Test(String name) {
super(name);
} public void run() {
while (i < 1000) {
synchronized (o) {
System.out.println(getName() + " " + i);
i++;
Thread.yield();
} }
} public static void main(String[] args) throws Exception { Test t = new Test("后台");
t.start();
while (i < 1000) {
synchronized (o) {
System.out.println(Thread.currentThread().getName() + " " + i);
i++;
Thread.yield();
}
}
System.out.println("停");
}
}
还有这个 ,对线程我也有点乱 坐等高手解决一下
我是这么理解的,不知道有没有问题你这两个线程主要运行的:
A:
while(i < 100)
{
i++;
System.out.println(getName() + " " + i); }B:
while(i<100)
{
System.out.println(Thread.currentThread().getName() + " " + i);
}cpu的时间片切换本来就不是一定执行一次A->B->A->B这样的顺序
很可能是A->A->B->ASystem.out.println(Thread.currentThread().getName() + " " + i);
这个操作是两步,你可以理解成
String str = Thread.currentThread().getName() + " " + i;
System.out.println(str);
那如果在这两步中间出现了时间片的切换,就会产生你现在的现象
所以 Thread.yield()应该是不用的,只要有那个同步块(synchronized (o) { ......})就行了
问题二:在执行线程的过程中,那个线程抢上这个变量,就执行那个线程。一个线程执行时,另一个线程就等待,除非它获得变量在执行。
synchronized关键字:当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。
Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor),当访问某个对象的synchronized方法时,表示将该对象上锁,此时其他任何线程都无法再去访问该synchronized方法了,直到之前的那个线程执行方法完毕后(或者是抛出了异常),那么将该对象的锁释放掉,其他线程才有可能再去访问该synchronized方法。
如果一个对象有多个synchronized方法,某一时刻某个线程已经进入到了某个synchronized方法,那么在该方法没有执行完毕前,其他线程是无法访问该对象的任何synchronized方法的。 synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法,有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,直接运行。它包括两种用法:synchronized 方法和 synchronized 块。
1. synchronized 方法:
声明是为了定义变量的作用范围和作用域
通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。