java线程怎么做标记?java线程如何同步?

线程是程序的一条执行线索,执行路径,是程序使用cpu的最小单位,其实说白了,线程是指进程中的一个执行流程,一个进程中可以运行多个线程,那java线程怎么做标记?下面来我们就来给大家讲解一下。

代码如下:

/*
停止线程:
1 stop 方法。
2 run 方法结束
怎么控制线程的任务结束?
任务中都会有循环结构(没有循环就不需要多线程了,开多线程就是怕这里循环影响其他),只要控制住循环就可以结束任务
控制循环通常就用定义标记来完成
*/
class StopThread implements Runnable
{
    private boolean flag = true;
    public void run()
    {
        while (flag)
        {
            System.out.println(Thread.currentThread()
                .getName() + "....");
        }
    }
    public void setFlag()
    {
        flag = false;
    }
}
class StopThreadDemo
{
    public static void main(String[] args)
    {
        StopThread st = new StopThread();
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(st);
        t1.start();
        t2.start();
        int num = 1;
        for (;;)
        {
            if (++num == 50)
            {
                st.setFlag(); //此处将标记变为false 停止线程
                break;
            }
            System.out.println("main..." + num);
        }
    }
}

java线程如何同步?

语法:

synchronized(锁对象)
{
    同步代码块
}

工作原理:

线程要执行同步代码块,必须先获得锁对象;

任意对象都可以作为锁对象, 任意对象都有一个内置锁;

一个锁对象最多被一个线程持有;

线程持有了锁对象后,会一直持有, 直到执行完同步代码块后才会释放锁对象;

package com.wkcto.chapter07.sync.p2;
/**
 * 银行帐户类
 * @author 蛙课网
 *
 */
public class BankAccount
{
    int balance = 10000; //余额 ,单位:万元
    private static final Object OBJ = new Object(); //常量
    //取钱的操作, 约定, 每次取钱1000
    public void withdraw()
    {
        synchronized(OBJ)
        { //一般使用常量作为锁对象
            System.out.println(Thread.currentThread()
                .getName() + "取钱 前, 余额为:" + balance);
            balance -= 1000;
            System.out.println(Thread.currentThread()
                .getName() + "取了1000万后, 余额为:" + balance);
        }
        /*
         * 1) xiaoming获得了CPU执行权, 执行withdraw()方法, 先获得OBJ锁对象, 执行同步代码块
         * 2) xiaoming在执行同步代码块期间, CPU执行权被baby抢走了, xiaoming转为就绪状态
         * babay获得CPU执行权, 要也执行同步代码块, 必须先获得OBJ锁对象,
         * 现在OBJ锁对象被xiaoming持有, baby线程转到等待锁对象池中阻塞
         * 3) xiaoming重新获得CPU执行权, 继续执行同步代码块, 执行完同步代码块后, 释放OBJ锁对象
         * 4) 等待锁对象池中的baby如果获得了锁对象, 转为就绪状态
         */
    }
}
package com.wkcto.chapter07.sync.p2;
/**
 * 定义一个线程类,模拟 从银行帐户 中取钱
 * @author 蛙课网
 *
 */
public class PersonThread extends Thread
{
    private BankAccount bankaccount; //银行帐户 
    public PersonThread(BankAccount bankaccount)
    {
        super();
        this.bankaccount = bankaccount;
    }
    @Override
    public void run()
    {
        bankaccount.withdraw();
    }
}
package com.wkcto.chapter07.sync.p2;
/**
 * 使用线程模拟多人同时从某一帐户中取钱
 * 线程同步
 * @author 蛙课网
 *
 */
public class Test01
{
    public static void main(String[] args)
    {
        //先开户
        BankAccount account = new BankAccount();
        //定义三个线程模拟三个人, 是从同一个帐户中取钱 
        PersonThread xiaoming = new PersonThread(account);
        PersonThread bingbing = new PersonThread(account);
        PersonThread baby = new PersonThread(account);
        xiaoming.setName("xiaoming");
        bingbing.setName("bingbing");
        baby.setName("baby");
        xiaoming.start();
        bingbing.start();
        baby.start();
    }
}

同步代码块

同步代码块要想实现同步,必须保证使用同一个锁对象

只要使用了同一个锁对象的同步代码块就可以同步

package com.wkcto.chapter07.sync.p3;
/**
 * 同步代码块, 只要使用相同的锁对象就可以实现同步
 * @author 蛙课网
 *
 */
public class Test01
{
    public static void main(String[] args)
    {
        PrintNum pNum = new PrintNum();
        //创建线程,调用m1()
        new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    pNum.m1();
                }
            })
            .start();
        //创建线程,调用m2()
        new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    //pNum.m2();//当使用this对象作为锁对象时, 可以同步
                    new PrintNum()
                        .m2(); //使用this作为锁对象, 不能同步,  与第一个线程的锁对象不是一个
                }
            })
            .start();
    }
}
package com.wkcto.chapter07.sync.p3;
/**
 * 定义类
 * 提供两个 方法,分别打印字符串
 * @author 蛙课网
 *
 */
public class PrintNum
{
    private static final Object OBJ = new Object(); //定义常量 
    public void m1()
    {
        //synchronized (OBJ) {//经常使用常量作为锁对象
        synchronized(this)
        { //有时也会使用this作为锁对象 , 就是调用m1()方法的对象
            for (int i = 1; i <= 200; i++)
            {
                System.out.println("wkcto is NB website");
            }
        }
    }
    public void m2()
    {
        //synchronized (OBJ) {
        synchronized(this)
        {
            for (int i = 1; i <= 200; i++)
            {
                System.out.println("bjpowernode is a good school");
            }
        }
    }
}
ackage com.wkcto.chapter07.sync.p4;
/**
 * 使用当前类的运行时类作为锁对象
 * @author 蛙课网
 *
 */
public class Test02
{
    public static void main(String[] args)
    {
        //创建线程, 打印wkcto
        new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    while (true)
                    {
                        printText("wkcto");
                    }
                }
            })
            .start();
        //创建线程, 打印bjpowernode
        new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    while (true)
                    {
                        printText("bjpowernode");
                    }
                }
            })
            .start();
    }
    private static final Object OBJ = new Object(); //常量 
    //静态方法,打印一个字符串
    public static void printText(String text)
    {
        //synchronized (OBJ) {
        synchronized(Test02.class)
        { //使用当前类的运行时类对象作为锁对象, 有人把它称为类锁
            //可以简单的理解 为把当前类的字节码文件作为锁对象
            for (int i = 0; i < text.length(); i++)
            {
                System.out.print(text.charAt(i));
            }
            System.out.println();
        }
    }
}

同步方法

package com.wkcto.chapter07.sync.p5;
/**
 * 同步实例方法, 就是把整个方法体作为同步代码块, 默认锁对象 是this对象
 */
public class Test01
{
    public static void main(String[] args)
    {
        Test01 obj = new Test01();
        //创建线程, 调用m1()
        new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    obj.m1();
                }
            })
            .start();
        //创建线程, 调用m2()
        new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    obj.m2();
                }
            })
            .start();
    }
    /*
     * 把整个方法体作为同步代码块,并且使用this作为锁对象时, 可以直接使用synchronized修饰方法, 称为同步方法 
     * 同步实例方法, 就是把整个方法体作为同步代码块, 默认锁对象 是this对象
     */
    public synchronized void m1()
    {
        for (int i = 1; i <= 500; i++)
        {
            System.out.println(Thread.currentThread()
                .getName() + "-->" + i);
        }
    }
    public void m2()
    {
        synchronized(this)
        {
            for (int i = 1; i <= 500; i++)
            {
                System.out.println(Thread.currentThread()
                    .getName() + "======>" + i);
            }
        }
    }
}
package com.wkcto.chapter07.sync.p5;
/**
 * 同步静态方法, 就是把整个方法体作为同步代码块, 默认锁对象 是当前类的运行时类对象
 */
public class Test02
{
    public static void main(String[] args)
    {
        //创建线程, 调用m1()
        new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    Test02.m1();
                }
            })
            .start();
        //创建线程, 调用m2()
        new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    Test02.m2();
                }
            })
            .start();
    }
    /*
     * 把整个方法体作为同步代码块,并且使用当前类的运行时类对象(Test02.class)作为锁对象时, 可以直接使用synchronized修饰方法, 称为同步方法 
     * 同步静态方法, 就是把整个方法体作为同步代码块, 默认锁对象 是当前类的运行时类对象(Test02.class)
     */
    public synchronized static void m1()
    {
        for (int i = 1; i <= 500; i++)
        {
            System.out.println(Thread.currentThread()
                .getName() + "-->" + i);
        }
    }
    public static void m2()
    {
        synchronized(Test02.class)
        {
            for (int i = 1; i <= 500; i++)
            {
                System.out.println(Thread.currentThread()
                    .getName() + "======>" + i);
            }
        }
    }
}

线程同步的目的是为了保护多个线程反问一个资源时对资源的破坏,所以对于同步,要时刻清醒在哪个对象上同步,这是关键!最后大家如果想要了解更多java入门知识,敬请关注奇Q工具网。

推荐阅读:

mybatis和hibernate的区别有哪些?mybatis工作原理是什么?

java如何开发网站?java开发网站有什么优势?

java程序员需要掌握的知识有哪些?如何提高java技能?