首先,你同步的是具体的某个Test实例, 对于那个实例来说,实际上只有一个线程访问了那个代码块,但是sum和other却是多个线程同时去进行访问,实际上这是不安全的,如果你想实现每次都输出10000的效果,那么正确的应该是在Test.class上加锁,而不是获取Test实例的锁,修改后的代码如下:
public?class?Test?extends?Thread?{
public?static?int?sum?=?10000;
public?static?int?other?=?0;
public?void?getMoney()?{
synchronized?(Test.class)?{
System.out.println(Thread.currentThread().getName()?+?"?开始执行");
sum?=?sum?-?100;
System.out.println("sum-100");
other?=?other?+?100;
System.out.println("other+100");
System.out.println(sum?+?other);
System.out.println(Thread.currentThread().getName()?+?"?执行完成");
}
public?void?run()?{
getMoney();
public?static?void?main(String[]?agrs)?{
Thread?t[]?=?new?Thread[10];
t[i]?=?new?Test();
t[i].start();
// 上面代码能得到你的结果
package threadgroup;
private String name;
private int delay;
name = sname;
delay = i_delay;
public void run() {
try {
sleep(delay);
} catch (InterruptedException e) {
System.out.println("多线程测试!\n" + name + "\n" + delay);
public class testMyThread {
public static void main(String[] args) {
th1.start();
public class threadDemo {
Thread t = Thread.currentThread();
t.setName("土嘎嘎的粉丝们大家好吗?");
System.out.println("正在进行的Thread是:" + t);
System.out.println("我不叫穆继超" + i);
} catch (Exception e) {
// TODO: handle exception
System.out.println("Thread has wrong" + e.getMessage());
Thread t1 = Thread.currentThread();
t1.setName("第一个主进程");
System.out.println("正在运行" + t1);
System.out.println("在创建一个进程");
System.out.println("使他进入第一个睡眠状态");
System.out.println("退出第一个进程");
System.out.println("进程" + i);
System.out.println("退出第二个进程");
public class RunThread implements Runnable{
String name;
Thread runner;
static boolean bool=true;
public RunThread(String threadName) {
name=threadName;
public void onStart()
{
runner = new Thread(this);
runner.setName(name);
runner.start();
String name=Thread.currentThread().getName();
System.out.println(name + " 线程运行开始!");
int index=0;
if(name.equals("小写字母"))
index='a';
else if(name.equals("大写字母"))
index='A';
while(!bool);
bool=false;
System.out.print((char)i+" ");
System.out.println();
bool=true;
e.printStackTrace();
System.out.println(name + " 线程运行结束!");
RunThread a=new RunThread("小写字母");
RunThread b=new RunThread("大写字母");
a.onStart();
b.onStart();
//System.out.println(" 线程运行开始!");
在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口.
对于直接继承Thread的类来说,代码大致框架是:
先看一个简单的例子:
【运行结果】:
A运行 0
A运行 1
B运行 0
B运行 1
我们会发现这些都是顺序执行的,说明我们的调用方法不对,应该调用的是start()方法.
当我们把上面的主函数修改为如下所示的时候:
然后运行程序,输出的可能的结果如下:
因为需要用到CPU的资源,所以每次的运行结果基本是都不一样的,呵呵.
注意:虽然我们今天这一节调用的是start()方法,但是实际上调用的还是run()方法的主体.
那么:为什么我们不能直接调用run()方法呢?
我的理解是:线程的运行需要本地操作系统的支持.
如果你查看start的源代码的时候,会发现:
注意我用红色加粗的那一条语句,说明此处调用的是start0().并且这个这个方法用了native关键字,次关键字表示调用本地操作系统的函数.因为多线程的实现需要本地操作系统的支持.
但是start方法重复调用的话,会出现java.lang.IllegalThreadStateException异常.
通过实现Runnable接口:
大致框架是:
来先看一个小例子吧:
【可能的运行结果】:
线程A运行 0
线程B运行 0
线程B运行 1
线程A运行 1
关于选择继承Thread还是实现Runnable接口?
其实Thread也是实现Runnable接口的:
其实Thread中的run方法调用的是Runnable接口的run方法.不知道大家发现没有,Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式.关于代理模式,我曾经写过一个小例子呵呵,大家有兴趣的话可以看一下:
Thread和Runnable的区别:
如果一个类继承Thread,则不适合资源共享.但是如果实现了Runable接口的话,则很容易的实现资源共享.
count= 1
大家可以想象,如果这个是一个买票系统的话,如果count表示的是车票的数量的话,说明并没有实现资源的共享.
我们换为Runnable接口:
最后提醒一下大家吧:
实现Runnable接口比继承Thread类所具有的优势:
①.):适合多个相同的程序代码的线程去处理同一个资源
所以,本人建议大家劲量实现接口.
Java 给多线程编程提供了内置的支持. 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务.
新建状态:
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态.它保持这个状态直到程序 start() 这个线程.
就绪状态:
当线程对象调用了start()方法之后,该线程就进入就绪状态.就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度.
运行状态:
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态.处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态.
阻塞状态:
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态.在睡眠时间已到或获得设备资源后可以重新进入就绪状态.可以分为三种:
等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态.
同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用).
其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态.当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态.
死亡状态:
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态.
以上就是土嘎嘎小编为大家整理的java多线程编程代码相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!