Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang
Artikel ini membawakan anda pengetahuan yang berkaitan tentang java, yang terutamanya memperkenalkan isu yang berkaitan dengan penyegerakan berbilang benang dan pustaka kelas teras Mari kita lihat bersama-sama adalah membantu.
Pembelajaran yang disyorkan: "tutorial video java"
1 Multi-threading
1.1 Proses
-
Proses : Ia adalah program berjalan
- digunakan oleh sistem untuk sumber peruntukan dan panggilan unit Bebas
- Setiap proses mempunyai ruang memori dan sumber sistem sendiri
-
Tiga ciri proses
- Kebebasan: proses adalah bebas antara satu sama lain dan mempunyai kawasan ingatan bebas mereka sendiri
- Dinamik: proses ialah program berjalan yang secara dinamik menduduki memori, CPU dan rangkaian Menunggu sumber
- Concurrency: CPU akan meninjau dan bertukar dalam cara perkongsian masa untuk melayani setiap proses secara bergilir-gilir Kerana kelajuan pensuisan adalah sangat pantas, rasanya kami melaksanakan pada masa yang sama (concurrency: sama Terdapat berbilang pelaksanaan pada masa yang sama)
1.2 Benang
-
Benang: Ia ialah satu proses Aliran kawalan berjujukan tunggal dalam ialah laluan pelaksanaan
- Berbenang tunggal: Proses hanya mempunyai satu laluan pelaksanaan
- Berbilang benang: Proses mempunyai berbilang laluan pelaksanaan
1.3 Kaedah pelaksanaan multi-threading
1.3.1 Kaedah 1: Mewarisi kelas Tread
-
Proses:
- 1 Tentukan kelas MyTread untuk mewarisi kelas Tread
- 2 🎜>3 Buat objek kelas MyTread
run()
4 Mulakan urutan: void start()
-
Kerana run() digunakan untuk merangkum kod yang dilaksanakan oleh benang
-
run(): merangkumkan kod yang dilaksanakan oleh thread dan memanggilnya secara terus, yang bersamaan dengan memanggil kaedah biasa
- start(): memulakan thread, dan kemudian memanggil kaedah JVM dalam thread run() ini
- Kelas MyTread:
package test;//1、定义一类MyTread继承Tread类public class MyThread extends Thread{ 2、在MyTread类中重写run()方法 @Override public void run() { for(int i=0;i
package test;public class Demo { public static void main(String[] args) { //3、创建MyTread类的对象 MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); //4、启动线程:void start():启动线程,由Java虚拟机调用此线程的run()方法 my1.start(); my2.start(); }}
Proses
- :
-
1 Tentukan kelas MyRunnable untuk melaksanakan antara muka Runnable
- 2 mengatasi kaedah
- dalam kelas MyRunnable
- 3 daripada kelas MyRunnable
run()
4 Cipta objek kelas Tread dan gunakan objek MyRunnable sebagai parameter pembina - 5
- Faedah:
- Elakkan Java Keterbatasan warisan tunggal
- 1.3.3 Kaedah 3: Laksanakan antara muka Boleh Panggil
package test;public class Demo { public static void main(String[] args) { //3、创建MyRunnable类的对象 MyRunnable mr = new MyRunnable(); //4、创建Tread类的对象,把MyRunnable对象作为构造方法的参数// Thread t1 = new Thread(mr);// Thread t2 = new Thread(mr); //Thread(Runnable target,String name) Thread t1 = new Thread(mr,"高铁"); Thread t2 = new Thread(mr,"飞机"); //5、启动线程 t1.start(); t2.start(); }}
Kaedah untuk menetapkan dan mendapatkan nama utas dalam kelas Thread
- MyThread类
package test;public class MyThread extends Thread{ //构造方法添加线程名称 public MyThread(){} public MyThread(String name) { super(name); } @Override public void run() { for(int i=0;i
- 测试类
package test;public class Demo { public static void main(String[] args) { /* MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); //2,void setName(Stringname) 将此线程的名称更改为等于参数name my1.setName("高铁"); my2.setName("飞机");*/ //3,通过构造方法设置线程名称 //需要自己定义的类中提供此带参构造方法,并通过super访问父类带参构造方法 /*MyThread my1 = new MyThread("高铁"); MyThread my2 = new MyThread("飞机"); my1.start(); my2.start();*/ //4,public static Thread currentThread() 返回对当前正在执行的线程对象的引用(可以返回main()方法中线程) System.out.println(Tread.currentThread().getName()); //main }}
1.5 线程调度
-
线程有两种调度模型
- 分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
- 抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些
Java使用的是抢占式调度模型
假如计算机只有一个CPU, 那么CPU在某一个时刻只能执行条指令, 线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的
Thread类中设置和获取线程优先级的方法
方法名 | 说明 |
---|---|
public final int getPriority() [praɪˈɔːrəti] | 返回此线程的优先级 |
public final void setPriority(int newPriority) | 更改此线程的优先级 |
- 线程默认优先级是5;线程优先级范围是:1-10
- 线程优先级高仅仅表示线程获取的CPU时间的几率高,但是要在次数比较多,或者多次运行的时候才能看到你想要的效果
package test;public class Demo { public static void main(String[] args) { ThreadPriority tp1 = new ThreadPriority(); ThreadPriority tp2 = new ThreadPriority(); ThreadPriority tp3 = new ThreadPriority(); tp1.setName("高铁"); tp2.setName("飞机"); tp3.setName("汽车"); //1,public final int getPriority() [praɪˈɔːrəti] 返回此线程的优先级// System.out.println(tp1.getPriority()); //5// System.out.println(tp2.getPriority()); //5// System.out.println(tp3.getPriority()); //5 //2,public final void setPriority(int newPriority) 更改此线程的优先级 System.out.println(Thread.MAX_PRIORITY); //10 System.out.println(Thread.MIN_PRIORITY); //1 System.out.println(Thread.NORM_PRIORITY); //5 //设置正确优先级 tp1.setPriority(5); tp2.setPriority(10); tp3.setPriority(1); tp1.start(); tp2.start(); tp3.start(); }}
1.6 线程控制
方法名 | 说明 |
---|---|
static void sleep(long millis) | 使当前正在执行的线程停留(暂停执行)指定的毫秒数 |
void join() | 等待这个线程死亡 |
void setDaemon(boolean on) [ˈdiːmən] | 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机很快将退出 (并不是立刻退出) |
案例:sleep()方法
- 线程类
package test;public class ThreadSleep extends Thread{ @Override public void run() { for(int i=0;i
- 测试类
package test;public class Demo { public static void main(String[] args) { ThreadSleep ts1 = new ThreadSleep(); ThreadSleep ts2 = new ThreadSleep(); ThreadSleep ts3 = new ThreadSleep(); ts1.setName("曹操"); ts2.setName("刘备"); ts3.setName("孙权"); ts1.start(); ts2.start(); ts3.start();// 曹操:0// 孙权:0// 刘备:0// 孙权:1// 曹操:1// 刘备:1// ... }}
案例:join()方法
package test;public class Demo { public static void main(String[] args) { ThreadJoin tj1 = new ThreadJoin(); ThreadJoin tj2 = new ThreadJoin(); ThreadJoin tj3 = new ThreadJoin(); tj1.setName("康熙"); tj2.setName("四阿哥"); tj3.setName("八阿哥"); tj1.start(); //2,void join() 等待这个线程死亡 try { tj1.join(); } catch (InterruptedException e) { e.printStackTrace(); } tj2.start(); tj3.start();// 康熙:0// 康熙:1// 康熙:2// 四阿哥:0// 四阿哥:1// 八阿哥:0// 八阿哥:1// 八阿哥:2// 四阿哥:2// ... }}
案例:setDaemon()方法
package test;public class Demo { public static void main(String[] args) { ThreadJoin tj1 = new ThreadJoin(); ThreadJoin tj2 = new ThreadJoin(); ThreadJoin tj3 = new ThreadJoin(); tj2.setName("关羽"); tj3.setName("张飞"); //设置主线程为刘备 Thread.currentThread().setName("刘备"); //3,void setDaemon(boolean on) 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出 tj1.setDaemon(true); tj2.setDaemon(true); tj1.start(); tj2.start(); for(int i=0;i<h3 id="strong-线程生命周期-strong"><strong>1.7 线程生命周期</strong></h3><p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/331836944d1895cfc26297fee263339c-0.png" class="lazy" alt="Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang"></p><h3 id="strong-数据安全问题之案例-买票-strong"><strong>1.8 数据安全问题之案例:买票</strong></h3><p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/331836944d1895cfc26297fee263339c-1.png" class="lazy" alt="Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang"><br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/331836944d1895cfc26297fee263339c-2.png" class="lazy" alt="Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang"></p>
-
为什么出现问题?(这也是我们判断多线程程序是否会有数据安全问题的标准)
- 是否是多线程环境
- 是否有共享数据
- 是否有多条语句操作共享数据
如何解决多线程安全问题呢?
基本思想:让程序没有安全问题的环境
-
怎么实现呢?
- 把多条语句操作共享 数据的代码给锁起来,让任意时刻只能有一一个线程执行即可
- Java提供 了同步代码块的方式来解决
1.9 线程同步_同步代码块
- 锁多条语句操作共享数据,可以使用同步代码块实现
- 格式
synchronized(任意对象) { 多条语句操作共享数据的代码}
好处:让多个线程实现先后依次访问共享资源,解决了多线程的数据安全问题
弊端:当线程很多的时候,因为每个线程都会去判断同步上的锁,这是很消耗资源的,无形中降低程序的运行效率
sellTicket类
package test;//1,定义一个类SellTicket实现Runnable接口,里面定义一个成员变量: private int tickets= 100;public class SellTicket implements Runnable{ private int tickets = 100; private Object obj = new Object(); //2,在ellTicket类中重写run0方法实现卖票, 代码步骤如下 @Override public void run() { while(true) { //tickes=100 //t1,t2,t3 //假设t1抢到CPU执行器 synchronized (obj){ //t1进来后把代码锁起来了 if (tickets > 0) { try { Thread.sleep(100); //t1休息100毫秒 } catch (InterruptedException e) { e.printStackTrace(); } //窗口1正在出售第100张票 System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票"); tickets--; //tickets=99 } //t1出来了,锁就被释放了 } } }}
- 测试类
package test;public class SellTicketDemo { public static void main(String[] args) { //创建SellTicket类的对象 SellTicket st = new SellTicket(); //创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称 Thread t1 = new Thread(st,"窗口1"); Thread t2 = new Thread(st,"窗口2"); Thread t3 = new Thread(st,"窗口3"); //启动线程 t1.start(); t2.start(); t3.start(); }}
1.10 线程同步_同步方法
- 作用:把出现线程安全问题的核心方法给锁起来,每次只能一个线程进入访问,其他线程必须在方法外面等待
-
同步方法:就是把synchronized关键字加到方法上;锁对象为:
this
- 格式:
修饰符 synchronized 返回值类型 方法名(方法参数) {}
- 格式:
-
同步静态方法:就是把synchronized关键字加到静态方法上面;锁对象为:
类名.class
- 格式:
修饰符 static synchronized 返回值类型 方法名(方法参数) {}
- 格式:
package test;public class SellTicket implements Runnable{//1非静态 private int tickets = 100; private static int tickets = 100; private Object obj = new Object(); private int x = 0; @Override public void run() { while(true) { if(x%2==0) {//1非静态 synchronized (this) { synchronized (SellTicket.class) { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票"); tickets--; //tickets=99 } } } else {// synchronized (obj) {// if (tickets > 0) {// try {// Thread.sleep(100);// } catch (InterruptedException e) {// e.printStackTrace();// }// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");// tickets--; //tickets=99// }// } sellTicket(); } x++; } }//1非静态// private synchronized void sellTicket() {// if (tickets > 0) {// try {// Thread.sleep(100);// } catch (InterruptedException e) {// e.printStackTrace();// }// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");// tickets--; //tickets=99// }// } private static synchronized void sellTicket() { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票"); tickets--; //tickets=99 } }}
1.11 线程安全的类(了解)
源码中方法都被synchronized修饰
StringBuffer
- 线程安全, 可变的字符序列
- 从版本JDK 5开始,被StringBuilder替代。通常应该使用StringBuilder类, 因为它支持所有相同的操作,但它更快,因为它不执行同步
Vector
- 从Java 2平台v1.2开始,该类改进了List接口, 使其成为Java Collections Framework的成员。 与新的集合实现不同,Vector被同步。 如果不需要线程安全的实现,建议使用ArrayList代替Vector
Hashtable
- 该类实现了一个哈希表,它将键映射到值。任何非null对象都可以用作键或者值
- 从Java 2平台v1.2开始,该类进行了改进,实现了Map接口,使其成为Java Collections Framework的成员。与新的集合实现不同,Hashtable被同步。 如果不需要线程安全的实现,建议使用HashMap代替Hashtable
Collections
类中static <t> List<t> snchronizedList(List<t> list)</t></t></t>
:返回由指定列表支持的同步(线程安全)的列表
package test;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;public class Demo { public static void main(String[] args) { //static <t> List<t> snchronizedList(List<t> list):返回由指定列表支持的同步(线程安全)的列表 Collection<string> list = Collections.synchronizedList(new ArrayList<string>()); /*源码都是返回Synchronized public static <t> List<t> synchronizedList(List<t> list) { return (list instanceof RandomAccess ? new Collections.SynchronizedRandomAccessList(list) : new Collections.SynchronizedList(list)); }*/ }}</t></t></t></string></string></t></t></t>
1.12 Lock锁
- Lock是接口不能直接实例化,采用实现类ReentrantLock来实例化(JDK5以后)
- ReentrantLock构造方法:
方法名 | 说明 |
---|---|
ReentrantLock() | 创建一个ReentrantLock的实例对象 |
- Lock中获得锁和释放锁方法:
方法名 | 说明 |
---|---|
void lock() | 获得锁 |
void unlock() | 释放锁 |
- 推荐使用
try{} finall{}
代码块来加锁和释放锁
package test;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class SellTicket implements Runnable{ private static int tickets = 100; private Lock lock = new ReentrantLock(); @Override public void run() { while(true) { try { lock.lock(); if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票"); tickets--; } }finally { lock.unlock(); } } }}
1.13 线程通讯
- 线程通信一定是多个线程在操作同一个资源才需要通信
方法名 | 说明 |
---|---|
public void wait() | 让当前线程进入到等待状态,此方法必须锁对象调用 |
public void notify() | 唤醒当前锁对象上等待状态的某个线程,此方法必须锁对象调用 |
public void notifyAll() | 唤醒当前锁对象上等待状态的全部线程,此方法必须锁对象调用 |
1.14 生产者消费者
1.14.1 生产者消费者概述
- 为了体现生产和消费过程中的等待和唤醒,Java就提供了几个方法供我们使用,这几个方法在Object类中
- Object类的等待和唤醒方法
方法名 | 说明 |
---|---|
void wait() | 导致当前线程等待,直到另一个线程调用该对象的 notify() 方法或 notifyAll() 方法 |
void notify() | 唤醒正在等待对象监视器的单个线程 |
void notifyAll() | 唤醒正在等待对象监视器的所有线程 |
1.14.2 生产者消费者案例
- 奶箱类
package test;//1:定义奶箱类public class Box { //定义一个成员变量,表示第x瓶奶 private int milk; //定义一个成员变量表示奶箱的状态 private boolean state = false; //提供存储牛奶和获取牛奶的操作 public synchronized void put(int milk) { //如果有牛奶等待消费 if(state) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没有牛奶,就生产牛奶 this.milk = milk; System.out.println("送奶工将第" + this.milk + "瓶奶放入奶箱"); //生产完毕后,修改奶箱状态 state = true; //唤醒其他等待线程 notifyAll(); } public synchronized void get() { //如果没有牛奶,就等到生产 if(!state) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果有牛奶,就消费牛奶 System.out.println("用户拿到第" + this.milk + "瓶奶"); //消费完毕后,修改奶箱状态 state = false; //唤醒其他等待线程 notifyAll(); }}
- 生产者类
package test;//2:生产者类(Producer):实现Runnable接口public class Producer implements Runnable { private Box b; public Producer(Box b) { this.b = b; } //重写run()方法,调用存储牛奶的操作 @Override public void run() { for (int i = 1; i
- 消费者类
package test;//3:消费者类(Customer);实现Runnable接口public class Customer implements Runnable{ private Box b; public Customer(Box b) { this.b = b; } //重写run()方法,调用获取牛奶的操作 @Override public void run() { while(true) { b.get(); } }}
- 测试类
package test;public class BoxDemo { public static void main(String[] args) { //创建奶箱对象,这是共享数据区域 Box b = new Box(); //创建生产者对象,把奶箱对象作为构造方法参数传递。因为在这个类中要谓用存储牛奶的操作 Producer p = new Producer(b); //创建消费者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用获取牛奶的操作 Customer c =new Customer(b); //创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递 Thread t1 = new Thread(p); Thread t2 = new Thread(c); //启动线程 t1.start(); t2.start();// 送奶工将第1瓶奶放入奶箱// 用户拿到第1瓶奶// 送奶工将第2瓶奶放入奶箱// 用户拿到第2瓶奶// 送奶工将第3瓶奶放入奶箱// 用户拿到第3瓶奶// 送奶工将第4瓶奶放入奶箱// 用户拿到第4瓶奶// 送奶工将第5瓶奶放入奶箱// 用户拿到第5瓶奶 }}
推荐学习:《java视频教程》
Atas ialah kandungan terperinci Teknik klasik Java untuk mencapai penyegerakan berbilang benang dan benang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

Panduan untuk TimeStamp to Date di Java. Di sini kita juga membincangkan pengenalan dan cara menukar cap waktu kepada tarikh dalam java bersama-sama dengan contoh.

Kapsul adalah angka geometri tiga dimensi, terdiri daripada silinder dan hemisfera di kedua-dua hujungnya. Jumlah kapsul boleh dikira dengan menambahkan isipadu silinder dan jumlah hemisfera di kedua -dua hujungnya. Tutorial ini akan membincangkan cara mengira jumlah kapsul yang diberikan dalam Java menggunakan kaedah yang berbeza. Formula volum kapsul Formula untuk jumlah kapsul adalah seperti berikut: Kelantangan kapsul = isipadu isipadu silinder Dua jumlah hemisfera dalam, R: Radius hemisfera. H: Ketinggian silinder (tidak termasuk hemisfera). Contoh 1 masukkan Jejari = 5 unit Ketinggian = 10 unit Output Jilid = 1570.8 Unit padu menjelaskan Kirakan kelantangan menggunakan formula: Kelantangan = π × r2 × h (4

PHP dan Python masing -masing mempunyai kelebihan sendiri, dan pilihannya harus berdasarkan keperluan projek. 1.Php sesuai untuk pembangunan web, dengan sintaks mudah dan kecekapan pelaksanaan yang tinggi. 2. Python sesuai untuk sains data dan pembelajaran mesin, dengan sintaks ringkas dan perpustakaan yang kaya.

PHP adalah bahasa skrip yang digunakan secara meluas di sisi pelayan, terutamanya sesuai untuk pembangunan web. 1.PHP boleh membenamkan HTML, memproses permintaan dan respons HTTP, dan menyokong pelbagai pangkalan data. 2.PHP digunakan untuk menjana kandungan web dinamik, data borang proses, pangkalan data akses, dan lain -lain, dengan sokongan komuniti yang kuat dan sumber sumber terbuka. 3. PHP adalah bahasa yang ditafsirkan, dan proses pelaksanaan termasuk analisis leksikal, analisis tatabahasa, penyusunan dan pelaksanaan. 4.Php boleh digabungkan dengan MySQL untuk aplikasi lanjutan seperti sistem pendaftaran pengguna. 5. Apabila debugging php, anda boleh menggunakan fungsi seperti error_reporting () dan var_dump (). 6. Mengoptimumkan kod PHP untuk menggunakan mekanisme caching, mengoptimumkan pertanyaan pangkalan data dan menggunakan fungsi terbina dalam. 7

Java ialah bahasa pengaturcaraan popular yang boleh dipelajari oleh pembangun pemula dan berpengalaman. Tutorial ini bermula dengan konsep asas dan diteruskan melalui topik lanjutan. Selepas memasang Kit Pembangunan Java, anda boleh berlatih pengaturcaraan dengan mencipta program "Hello, World!" Selepas anda memahami kod, gunakan gesaan arahan untuk menyusun dan menjalankan program, dan "Hello, World!" Pembelajaran Java memulakan perjalanan pengaturcaraan anda, dan apabila penguasaan anda semakin mendalam, anda boleh mencipta aplikasi yang lebih kompleks.
